Change a Date Object's Timezone in Java? - java

Turkey has two TimeZone GMT+2 and GMT+3.
I want to change the GMT+2 dates into GMT+3, but I want to protect hours and minutes that in GMT+2 TimeZone.
I want to take hours and minutes, and then set these values into GMT+3 TimeZone date. At result there must be no change in hours and minutes but the timeZone must be change only. At function toconvert date is must be GMT+2 format, but the return value must be GMT+3 format. How to do it clearly?
public static Date convertTimezone(Date toConvert) {
Date date = new Date();
date.setYear(toConvert.getYear());
date.setMonth(toConvert.getMonth());
date.setHours(toConvert.getHours());
date.setMinutes(toConvert.getMinutes());
return date;
}

In Java a Date represents a point in time, nothing else. This means that Date knows nothing about how it is printed, which time zone etc...
Time Zone is therefore something you set when printing the Date. The class DateFormat is typically used for printing and the time zone is part of the properties you can set on DateFormat. Typically, people use the subclass SimpleDateFormat.

java.util.Date cannot track your Timezone details. Use Calendar instead

You shouldn't use a Date object in this case. Use Calendar instead.
public static Calendar convertTimezone(Calendar toConvert) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+3"));
calendar.set(Calendar.YEAR, toConvert.get(Calendar.YEAR));
calendar.set(Calendar.MONTH, toConvert.get(Calendar.MONTH));
calendar.set(Calendar.DATE, toConvert.get(Calendar.DATE));
calendar.set(Calendar.HOUR_OF_DAY, toConvert.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, toConvert.get(Calendar.MINUTE));
return calendar;
}

You can make use of Calender API to convert one timezone to other
public static Date convertTimezone(Date toConvert) {
Calender calendar = Calendar.getInstance();
calender.setTime(toConvert);
int hour = calender.get(Calender.HOUR_OF_DAY);
int minutes = calender.get(Calender.MINUTE);
Calendar ret = new GregorianCalender(timeZone); //timeZone is destination TimeZone
ret.setTimeInMillis(calendar.getTimeInMillis() +
timeZone.getOffset(calendar.getTimeInMillis()) -
TimeZone.getDefault().getOffset(calendar.getTimeInMillis()));
ret.set(Calender.HOUR_OD_DAY, hour);
ret.set(Calender.MINUTE, minutes);
return ret.getTime();
}

Related

Java Calendar and Time UTC to BST

I get a string in the format yyyy-MM-dd HH:mm which represents a Date and Time in UTC.
Next step is to put this into a Calendar (with TimeZone UTC).
In addition need to also create a separate Calendar which has converted the UTC to "Europe/London" timeZone (GMT/BST).
After that I need to be able to detect if the "Europe/London" calendar has a DST (Day Light Savings Offset).
The code below will show you how far I have got and it runs ok on a UK based computer whose default System Timezone is GMT. However when I run it on a pc whose timezone is UTC it fails. It seems to not be able to tell me if there is an DST_offset (its always zero).
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2016);
cal.set(Calendar.MONTH, 1);
cal.set(Calendar.DAY_OF_MONTH, 27);
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 35);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
//This is required as Java Date JAN starts at 0.
int MonthCon = cal.get(Calendar.MONTH)-1;
cal.set(Calendar.MONTH, MonthCon);
Date d = cal.getTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC: " + f.format(d));
f.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println("BST: " + f.format(d));
//Creates a BST calendar of the same UTC time
String dateStrBST = f.format(d);
SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Date dateObjBST = curFormater.parse(dateStrBST);
System.out.println("BSTNewDate: " + f.format(dateObjBST));
Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("BST"));
calBST.setTime(dateObjBST);
System.out.println("Current TimeZone is : " + calBST.getTimeZone());
int offset = calBST.get(Calendar.DST_OFFSET);
System.out.println("Day Light Savings: "+offset);
System.out.println("Transition Day: "+isDSTTransitionDay(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH))+" Transition Type: "+DSTtransitionType(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH)));
Unfortunately I need to be able to detect if any particular day is a transition day, that is to say a day that changes from DST on/off or off/on. Again this works on the local computer but not on the UTC timezone one.
private static boolean isDSTTransitionDay(int year, int month, int day) throws ParseException
{
Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calStartofDay.set(Calendar.YEAR, year);
calStartofDay.set(Calendar.MONTH, month);
calStartofDay.set(Calendar.DAY_OF_MONTH, day);
calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
calStartofDay.set(Calendar.MINUTE, 0);
calStartofDay.set(Calendar.SECOND, 1);
Date dStartofDay = calStartofDay.getTime();
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
f.setTimeZone(TimeZone.getTimeZone("Europe/London"));
String dateStrUTCtoBST = f.format(dStartofDay);
SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Date dateObjBST = curFormater.parse(dateStrUTCtoBST);
Calendar calBST = Calendar.getInstance();
calBST.setTime(dateObjBST);
int offsetStart = calBST.get(Calendar.DST_OFFSET);
calBST.add(Calendar.HOUR_OF_DAY, 23);
int offsetEnd = calBST.get(Calendar.DST_OFFSET);
//System.out.println("Start: "+offsetStart+" End: "+offsetEnd);
if (offsetEnd == offsetStart)
{
return false;
}else
{
//if(offsetStart<offsetEnd) {System.out.println("Transition to BST");}else{System.out.println("Transition to UTC/GMT");};
return true;
}
}
So on the UTC computer it fails miserably as it always puts Calendar.DST_OFFSET at zero. I have clearly misunderstood something along the way so any help/clarity would be good.
I pretty much have to keep Calendars as the rest of the code uses it but I realise the Java8 has many more fancy ways to do things.
Please allow me to be honest, I tried to read your code and didn’t really understand your way of trying to obtain what you want. If you can use Java 8, I recommend switching to using the Java 8 date and time classes. With these your job isn’t very complicated. For the demonstration I have chosen last October 30, the date when Britain (and EU) changed back from summer time (daylight saving time) to standard time.
String originalDate = "2016-10-30 23:35";
LocalDateTime localTime = LocalDateTime.parse(originalDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
ZonedDateTime utcTime = localTime.atZone(ZoneOffset.UTC);
ZonedDateTime bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
// the summer time offset is how many milliseconds?
long dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0
// try the same at start of day (midnight)
utcTime = utcTime.toLocalDate().atStartOfDay(ZoneOffset.UTC);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 3600000
// and next midnight
utcTime = utcTime.plusDays(1);
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London"));
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime());
System.out.println(dstOffset); // prints 0
You are using
Calendar calBST = Calendar.getInstance();
That sets calBST to the computer's timezone (on the UTC computer, it will be UTC).
calBST.setTime(dateObjBST); sets the time, not the timezone.
Try using getInstance(TimeZone zone) there also.
In any case, I would replace your code like this:
Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calStartofDay.set(Calendar.YEAR, 2017);
calStartofDay.set(Calendar.MONTH, 0);
calStartofDay.set(Calendar.DAY_OF_MONTH, 21);
calStartofDay.set(Calendar.HOUR_OF_DAY, 00);
calStartofDay.set(Calendar.MINUTE, 0);
calStartofDay.set(Calendar.SECOND, 1);
Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("Europe/London"));
calBST.setTimeInMillis(calStartofDay.getTimeInMillis());
// use this to check the time
System.out.printf("%tc%n", calBST);
Also, from the Calendar docs, be careful about this:
set(f, value) changes calendar field f to value. In addition, it sets
an internal member variable to indicate that calendar field f has been
changed. Although calendar field f is changed immediately, the
calendar's time value in milliseconds is not recomputed until the next
call to get(), getTime(), getTimeInMillis(), add(), or roll() is made.
Thus, multiple calls to set() do not trigger multiple, unnecessary
computations. As a result of changing a calendar field using set(),
other calendar fields may also change, depending on the calendar
field, the calendar field value, and the calendar system. In addition,
get(f) will not necessarily return value set by the call to the set
method after the calendar fields have been recomputed. The specifics
are determined by the concrete calendar class.

java.util.date getActualMaximum(Calendar.DAY_OF_MONTH) [duplicate]

I am having issues with the calculation of when the next Last Day of the Month is for a notification which is scheduled to be sent.
Here is my code:
RecurrenceFrequency recurrenceFrequency = notification.getRecurrenceFrequency();
Calendar nextNotifTime = Calendar.getInstance();
This is the line causing issues I believe:
nextNotifTime.add(recurrenceFrequency.getRecurrencePeriod(),
recurrenceFrequency.getRecurrenceOffset());
How can I use the Calendar to properly set the last day of the next month for the notification?
Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);
This returns actual maximum for current month. For example it is February of leap year now, so it returns 29 as int.
java.time.temporal.TemporalAdjusters.lastDayOfMonth()
Using the java.time library built into Java 8, you can use the TemporalAdjuster interface. We find an implementation ready for use in the TemporalAdjusters utility class: lastDayOfMonth.
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
LocalDate now = LocalDate.now(); //2015-11-23
LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth()); //2015-11-30
If you need to add time information, you may use any available LocalDate to LocalDateTime conversion like
lastDay.atStartOfDay(); //2015-11-30T00:00
And to get last day as Date object:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
Date lastDayOfMonth = cal.getTime();
You can set the calendar to the first of next month and then subtract a day.
Calendar nextNotifTime = Calendar.getInstance();
nextNotifTime.add(Calendar.MONTH, 1);
nextNotifTime.set(Calendar.DATE, 1);
nextNotifTime.add(Calendar.DATE, -1);
After running this code nextNotifTime will be set to the last day of the current month. Keep in mind if today is the last day of the month the net effect of this code is that the Calendar object remains unchanged.
Following will always give proper results:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, ANY_MONTH);
cal.set(Calendar.YEAR, ANY_YEAR);
cal.set(Calendar.DAY_OF_MONTH, 1);// This is necessary to get proper results
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
cal.getTime();
You can also use YearMonth.
Like:
YearMonth.of(2019,7).atEndOfMonth()
YearMonth.of(2019,7).atDay(1)
See
https://docs.oracle.com/javase/8/docs/api/java/time/YearMonth.html#atEndOfMonth--
Using the latest java.time library here is the best solution:
LocalDate date = LocalDate.now();
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
Alternatively, you can do:
LocalDate endOfMonth = date.withDayOfMonth(date.lengthOfMonth());
Look at the getActualMaximum(int field) method of the Calendar object.
If you set your Calendar object to be in the month for which you are seeking the last date, then getActualMaximum(Calendar.DAY_OF_MONTH) will give you the last day.
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = sdf.parse("11/02/2016");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
System.out.println("First Day Of Month : " + calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
System.out.println("Last Day of Month : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
Kotlin date extension implementation using java.util.Calendar
fun Date.toEndOfMonth(): Date {
return Calendar.getInstance().apply {
time = this#toEndOfMonth
}.toEndOfMonth().time
}
fun Calendar.toEndOfMonth(): Calendar {
set(Calendar.DAY_OF_MONTH, getActualMaximum(Calendar.DAY_OF_MONTH))
return this
}
You can call toEndOfMonth function on each Date object like Date().toEndOfMonth()

Creating a custom Date object from Calendar?

I need to create a custom Date object. I get a user input in 24 hr format like hh:mm i.e. 17:49 hrs.
I want to set the hours and minutes as 17 and 49 respectively keeping other details like month , year , day as per the current time.For e.g if today is Dec 16,2014 and the time is 16:00 hrs , then i want a date object as Dec 16,2014 with time as 17:49 hrs. I know i can do this using deprecated apis , however i do not want to use them.I need the date object because i need to pass it to a java timer as java timer does not support any calendar object.
The user input comes as a string and i can parse that string using new SimpleDateFormat(HH:mm) contructor.
I tried using the Calendar.set apis but had no success.
Could some one give some direction on how to proceed.
PS. Sorry , i can't use Joda time :)
EDIT
Since getHours() and getMinutes() are deprecated and have been replaced with Calendar.HOUR_OF_DAY and Calendar.MINUTE respectively, you could use an intermediary calendar object or set the YEAR and DAY to current values.
There is a problem though, if you input next day hour like 24:01 it won't move to the next day. The previous answer, with splitting of string did the overflowing correctly.
public static void main(String[] args) throws ParseException {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
final String timeInterval = "12:01";
Date date = simpleDateFormat.parse(timeInterval);
final Calendar calendar = Calendar.getInstance(); //calendar object with current date
calendar.setTime(date); //set date with day january 1 1970, this is because you parsed only the time part, the date objects assumes you start from it's lowest value, try a System.out.println(date) before this to see.
calendar.set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR));
calendar.set(Calendar.DATE,Calendar.getInstance().get(Calendar.DATE));
calendar.set(Calendar.MONTH, Calendar.getInstance().get(Calendar.MONTH))
date = calendar.getTime();
System.out.println(date);
}
You can use Calendar to set the time, then extract the date with .getTime() method, which returns a java.util.Date
The idea is to split your string into two parts based on the separator :.
Then simply initialize the calendar and set the hour and minutes with those values.
public static void main(String[] args) throws ParseException {
final String userInput = "17:49";
final String[] timeParts=userInput.split(":");
Calendar cal=Calendar.getInstance(); //current moment calendar
cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeParts[0]));
cal.set(Calendar.MINUTE, Integer.parseInt(timeParts[1]));
cal.set(Calendar.SECOND,0); //if you don't care about seconds
final Date myDate=cal.getTime(); //assign the date object you need from calendar
//use myDate object anyway you want ...
System.out.println(myDate);
}
The following code works fine , however i don't want to use any deprecated apis.
...
...
String timeInterval = "18:01";
Date date = simpleDateFormat.parse(timeInterval);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, date.getHours());
calendar.set(Calendar.MINUTE, date.getMinutes());
date = calendar.getTime();
System.out.println(date);
...
...

set calendar object hour to 0

this is my code
TimeZone timeZone = TimeZone.getTimeZone("UTC");
Calendar calendar = Calendar.getInstance(timeZone);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
Timestamp start = new Timestamp(calendar.getTime().getTime());
but the timestamp result is for instance = 2014-09-30 02:00:00.0 I´m not able to set the hours to 0.
Any suggestions.
Once you call Calendar.getTime() you get a Date object which is an instant in time which has no timezone info.
When you want to print or present this instance, the formatter will use the default time zone if not explicitly specified, which in your case is not UTC but maybe CET.
When you convert this instant to a String, you also have to tell in which timezone you want it to present. You have to specify UTC timezone there as well.
For example if using SimpleDateFormat, you can use its setTimeZone() method.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(start));
Also if your result is from your database, you have to use a timestamp SQL type without timezone or with the UTC timezone.
I guest icza is right.
To be sure, try this :
Timestamp start = new Timestamp(calendar.getTime().getTime());
System.out.println(start.getTimezoneOffset());

Convert integer to dates

I'm stuck at this part where I must use integer to get the individual year, month ,day, hour and min to string it into a date format, e.g. 24/01/2004 13:00.
Date Date = (years,month,day,hour,min);// error Part
System.out.println(Date);
Use Calendar#set(..)
Calendar calendar = Calendar.getInstance();
calendar.set(year,month-1,day,hour,min);//month is 0 based
Date date = calendar.getTime();
The JodaTime library is very practical to create Dates just the way you were looking for:
// omission of DateTimeZone parameter results in use of JVM default time zone
DateTime dt = new DateTime( years, month, day, hour, min, DateTimeZone.forID( "Europe/Berlin" ) );
Date date = dt.toDate();
http://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html
Make use of link below to Set attributes of Date class.
Date releaseDate = new Date();
releaseDate.setYear(year);
releaseDate.setMonth(month);
......
releaseDate.setMinutes(min);
Refer Java docs Here
try this:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.YEAR, year);
.
.
.
DateFormat formatData = new SimpleDateFormat("d/M/yyyy H:mm");
System.out.println(formatData.format(cal.getTime()));
If you want to get a headstart on Java 8, you could use joda-time's LocalDateTime class, which shares quite a few method signatures with the Java 8 LocalDateTime. Though unfortunately it doesn't have LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute) or similar methods; instead, use the constructors.

Categories

Resources