Possible problem with TimeZone.getOffset() ?
When converting from GMT to a local time zone, I noticed that the getOffset() function does not seem to take into account daylight saving time. Tested using Java 1.5.0_08 and Java 1.6 - Is this normal behaviour?
For example, this works properly when displayed:
// Calendar gmtTime contains the GMT time information
Calendar localCal = new GregorianCalendar();
localCal.setTimeInMillis(gmtTime.getTimeInMillis());
But this localDate variable does not display correctly:
// getOffset parameters are found directly from gmtTime.get()
TimeZone localTimeZone = TimeZone.getDefault();
int offset = localTimeZone.getOffset(era, year, month, day, dayOfWeek, milliseconds);
Date localDate = new Date(gmtCal.getTimeInMillis() + offset);
Even creating another GMT Calendar object with the offset doesn't seem to take into account daylight saving time
Calendar gmtToLocal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
gmtToLocal.setTimeInMillis(gmtCal.getTime().getTime() + offset);
What I'm also confused about is why the localDate and gmtToLocal times are not the same when outputted... can someone please explain these things to me and let me know the recommended way to do the conversions? I've been using 3/11/2007 07:59 -> 08:00 for testing.
Thanks!
[1348 byte] By [
SDN_Davea] at [2007-11-26 21:27:37]

What is the expected output, and what is the actual output (give examples)Make sure your computer is set to the right time zone, funny that you ask this question right when its been all over the news that DST is changing early and it could cause problems everywhere.
Actual output:
For 3/11/2007 7:59:59 GMT (correct for everything except localDate)
gmtTime = 7:59:59 GMT
localCal = 1:59:59 CST
localDate = 3/10/2007 19:59:59
gmtToLocal = 1:59:59
For 3/11/2007 8:00:00 GMT (correct only for gmtTime and localCal)
gmtTime = 8:00:00 GMT
localCal = 3:00:00 CST
localDate = 3/10/2007 20:00:00
gmtToLocal = 2:00:00
The expected result is that the localDate and gmtToLocal are the same as the localCal date. I don't know why the localDate is so off, it's as if it's subtracting the offset twice for some reason. My local time zone is CST (verifiable in the output for localCal above). The DST thing is precisely the reason that I posted this - an application was using the getOffset method converted the timezone improperly - it was 2 hours behind from 3:00-4:00 AM CST the night of the change, went to one hour behind from 4:00 AM-2:00 PM and then properly converted the GMT. I believe that if I understood what the problem is in the code above with using getOffset for localDate and gmtToLocal above I could better understand what happened.
> Date localDate = new Date(gmtCal.getTimeInMillis() + offset);
I wouldn't expect that to be correct.
A Date (and time) is a point in time, which is a certain number of milliseconds since "epoch".
gmtCal.getTimeInMillis() returns that point in time. When you add something to it, it's a different point in time. So when you construct a Date given that incorrect point in time, it shouldn't surprise you that it is giving you the wrong time.
Thank you all, I appreciate the help - I was definetely thinking about how the time is stored improperly. I removed adding the offset to the date and found it gives the correct time and even accounts for DST as expected. It also makes sense that the Calendar based on GMT does not give the proper value because GMT is not supposed to take into account DST. I'm going to try to work out why it seemed to be working before and then make the appropriate changes.
Alright, it looks like I'm still having problems... I'm trying to read a GMT timestamp in the database and convert it to a local Date... sounds easy... here's what I'm doing:
Calendar gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// dbTimestamp is 2007-03-11 07:07 AM
gmtCalendar.setTimeInMillis(dbTimestamp);
The problem is that this is what is then in gmtCalendar:
Using get(Calendar.FIELDs): 2/11/2007 13:07:11 PM
Using getTime().toString(): Sun Mar 11 08:07:11 CDT 2007
As you can see, the month is completely wrong when using Get() and the timezone is wrong when using getTime(). Can someone provide some pointers about what I might be doing wrong?
> Alright, it looks like I'm still having problems...
> I'm trying to read a GMT timestamp in the database
> and convert it to a local Date.
Aha. Why didn't you say so before. Here's my code which does that:Timestamp ts = orders.getTimestamp("DateTime");
Calendar badcal = Calendar.getInstance();
badcal.setTime(ts);
Calendar goodcal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
goodcal.set(Calendar.YEAR, badcal.get(Calendar.YEAR));
goodcal.set(Calendar.MONTH, badcal.get(Calendar.MONTH));
goodcal.set(Calendar.DAY_OF_MONTH, badcal.get(Calendar.DAY_OF_MONTH));
goodcal.set(Calendar.HOUR_OF_DAY, badcal.get(Calendar.HOUR_OF_DAY));
goodcal.set(Calendar.MINUTE, badcal.get(Calendar.MINUTE));
goodcal.set(Calendar.SECOND, badcal.get(Calendar.SECOND));
Date goodTs = goodcal.getTime();
Thank you - that worked but it seems illogical to me to create a calendar in the local time zone to read the GMT time in the database, then have to instantiate a calendar in GMT in order to get the local time.. is there a more logical way to do it? (Perhaps using the getOffset method (although that doesn't appear to take into account DST.))
For reference, here's what I got using some methods so far (I think I typoed before):
Test Timestamp In Database: 2007-03-11 08:07:11.017
setTime with Calendar.getInstance():
- Output the get(Calendar.FIELD) values: 02-11-2007 08:07:11
- Output with getTime().toString(): Sun Mar 11 08:07:11 CDT 2007
- Note: time values are the originals but the time zone is not
- Note: The 02 for the month with Calendar.get() is March because the enumeration starts at 0
setTime with Calendar.getInstance(TimeZone.getTimeZone("GMT")):
- Output the get(Calendar.FIELD) values: 02-11-2007 13:07:11
- Output with getTime().toString(): Sun Mar 11 08:07:11 CDT 2007
- Note: CDT is supposed to be GMT-5... I don't understand this.
Transferring from GMT to local calendar with set functions:
- Output the get(Calendar.FIELD) values: 02-11-2007 13:07:11
- Output with getTime().toString(): Sun Mar 11 13:07:11 CDT 2007
Transferring from local calendar to GMT calendar with set:
- Output with get(Calendar.FIELD) values: 02-11-2007 08:07:11
- Output with getTime().toString(): Sun Mar 11 03:07:11 CDT 2007
- Note: getTime().toString() is right! At last!
> Thank you - that worked but it seems illogical to me
> to create a calendar in the local time zone to read
> the GMT time in the database, then have to
> instantiate a calendar in GMT in order to get the
> local time.. is there a more logical way to do it?
I knew I should have provided an explanation.
The point of the "badcal" variable is that the database driver acts as if the value in the database represents a time in your timezone. It doesn't really, but you have to humour the driver. It's always better not to fight against software. (Okay, this part is logical but it doesn't necessarily look that way.) Pretending that it does that, you can get out of "badcal" the year, month, day, hour, minute, and second values that actually represent the time in GMT.
Now you have some numbers that when you interpret them as year, month, day, hour, minute, and second represent some time in GMT. You want to know what time they represent in your timezone. So: you create a calendar whose timezone is GMT. You set its year, month, day, hour, minute, and second to those numbers. Now you have a Calendar object that represents the correct point in time. That's all you need. You're done. It's all perfectly logical.
And it works. I don't have to do any of that business mucking about with offsets and daylight saving time. The Calendar class does all of that internally. That's what it's for.
(Actually: this doesn't work perfectly. If the GMT time were between 2 AM and 3 AM yesterday, there isn't any such time of day in my timezone because we skipped that hour. I have no idea what the database driver would do with such a time of day. But you are going to have the same problem with whatever you come up with, I think. The only perfect solution is to run your code on a machine that is configured to be in GMT.)
Thank you, that's a big help. :)
In regards to your month being off by one, it isn't really. It is returning the constant Calendar.MARCH, which is the int 2.
> Alright, it looks like I'm still having problems...
> I'm trying to read a GMT timestamp in the database
> and convert it to a local Date.
Aha. Why didn't you say so before. Here's my code which does that:
Hey clap,
In the code what you have given, is it possible to read the GMT timestamp from the database and convert it to a local Date. If so, what does the below line says:
Timestamp ts = orders.getTimestamp("DateTime");
what is orders in this code?
Please help me..By default we are storing the date value into the database in a GMT format. But while displaying, we have to convert that GMT date to local date and show it on the page. Am really struggling a lot to get this.
Thanks in advance
Kannan