argonath88
argonath88

Reputation: 453

Time Zones in Java

I'm working on a security signature in java that also verifies the date and time the call is being made. The POST call arrives with something like

String date = "Sat, 27 Apr 2013 01:11:30 GMT"
SimpleDateFormat RFC1123Format = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);

And I'm able to parse it

Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);

System.out.println("Date Header (GMT TIME): " + gmtTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + gmtTime.get(Calendar.HOUR_OF_DAY));

Calendar currentTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
currentTime.setTimeInMillis(System.currentTimeMillis());

System.out.println("System Date (LA TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (LA TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));

currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));

System.out.println("System Date (GMT TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));

System.out.println("Diff: " + Math.abs(gmtTime.getTimeInMillis() - currentTime.getTimeInMillis()));

However the printout I get differs by 1 entire hour.

Date Header (GMT TIME): 1367025090000 ms
Hour of day (GMT TIME): 1
System Date (LA TIME): 1367022298441 ms
Hour of day (LA TIME): 0
System Date (GMT TIME): 1367022298441 ms
Hour of day (GMT TIME): 0
Diff: 2791559

Any ideas?

Upvotes: 0

Views: 248

Answers (3)

argonath88
argonath88

Reputation: 453

Fixed it myself by adding an extra verification to check if Daylight Savings is being observed. This is the final code:

Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);

Calendar currentTime = Calendar.getInstance();
currentTime.setTimeInMillis(System.currentTimeMillis());
boolean DST = false;
if(currentTime.getTimeZone().inDaylightTime(currentTime.getTime())) {
    DST = true; 
}
currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));
if(DST) { 
    currentTime.set(Calendar.HOUR_OF_DAY, currentTime.get(Calendar.HOUR_OF_DAY) + 1); 
    .
    .
    .
    <code to handle last day of month and month change as a result of the hour adjustment>
}

Thanks @gangqinlaohu for your suggestion.

Upvotes: 0

scottb
scottb

Reputation: 10084

You don't give your formatter the calendar that you are using to represent your timestamps.

In this case, your calendar is set to represent timestamps in GMT. GMT is a synonym for UTC and UTC never observes any adjustment for DST. Your formatter, however, by default must convert your supplied string with the system default calendar as the basis, which likely does observe DST.

If this is the case, you can get consistent reporting by making sure that your formatter is using the same calendar that you are using to represent your date/times. Try this:

SimpleDateFormat RFC1123Format = new SimpleDateFormat();
GregorianCalendar gc - new GregorianCalendar(TimeZone.getTimeZone("GMT"));

RFC1123Format.setCalendar(gc);
RFC1123Format.applyPattern("EEE, dd MMM yyyyy HH:mm:ss z");

gc.setTime(RFC1123Format.parse(yourDateString));

Upvotes: 0

dodoconr
dodoconr

Reputation: 113

You can use JodaTime >> http://joda-time.sourceforge.net/ that implements TimeZone Calculations more efficiently than Java calendar

Upvotes: 1

Related Questions