Dirk Groeneveld
Dirk Groeneveld

Reputation: 2637

Correct time zone support in J2ME

I need accurate time zone support in my BlackBerry app. Because it runs J2ME, Joda Time is not an option. With the help of some others on SO I've figured out how to make Java's built-in time zone support work for me, but it turns out that it still gets the switchover from daylight-savings to non-daylight-savings wrong. You can try it yourself, even on Java 6:

TimeZone zone = TimeZone.getTimeZone("America/Los_Angeles");
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(zone);

calendar.set(2011, Calendar.MARCH, 13, 1, 0, 0);      
System.out.println(zone.getOffset(1, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK), calendar.get(Calendar.MILLISECOND)));

calendar.set(2011, Calendar.MARCH, 13, 6, 0, 0);
System.out.println(zone.getOffset(1, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK), calendar.get(Calendar.MILLISECOND)));

calendar.set(2011, Calendar.MARCH, 13, 23, 59, 59);
System.out.println(zone.getOffset(1, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK), calendar.get(Calendar.MILLISECOND)));

calendar.set(2011, Calendar.MARCH, 14, 0, 0, 1);
System.out.println(zone.getOffset(1, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK), calendar.get(Calendar.MILLISECOND)));

Switchover in 2011 is on March 13th, at 2am, but Java has it at midnight of March 14th. That means it's wrong for almost an entire day. That's unacceptable.

I have embarked upon implementing my own tzdata parser based on this, and shipping the tzdata files with my app, but I'm wondering if there is a better way. Do you know one? I can't be the first one to hit this problem, can I?

Upvotes: 2

Views: 1366

Answers (1)

Dirk Groeneveld
Dirk Groeneveld

Reputation: 2637

I figured it out. Java is not to blame, I am.

The problem is that I used calendar.get(Calendar.MILLISECOND) for the last parameter of TimeZone.getOffset(). That value is the millisecond portion of the date in the calendar, but what TimeZone.getOffset() expects is the number of milliseconds that have passed over the course of the entire day.

This is the corrected code:

calendar.set(2011, Calendar.MARCH, 13, 1, 0, 0);      
int millis =
    calendar.get(Calendar.MILLISECOND) +
    calendar.get(Calendar.SECOND) * 1000 +
    calendar.get(Calendar.MINUTE) * 60 * 1000 +
    calendar.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000;
System.out.println(zone.getOffset(1, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.DAY_OF_WEEK), millis));

Upvotes: 3

Related Questions