Java – Date gives one day less than actual date while converting from date to calendar

calendardatejava

I am passing date from front end which is IST(date of indian timezone). And in java code i am converting date to calendar using the following code(This is happening in the server which is there in US PST timezone).

Calendar cal = Calendar.getInstance();
int offset = date.getTimezoneOffset();
logger.info("Calendar Instance - " + cal);
cal.setTime(date);
logger.info("Calendar Instance after setting date - " + cal);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
logger.info("Calendar Instance after setting zeros - " + cal);
return cal;

so when i see the last log the day of the month will be one day less than what i passed.eg. if i pass 22/06/2015 IST it shifts to 21/06/2015. so after processing finally it displays 21/06/2015 in the list of data which is in another UI page.

Best Answer

This happens because JVM on server side and JVM on client side use different time zones by default Java TimeZone:

Typically, you get a TimeZone using getDefault which creates a TimeZone based on the time zone where the program is running. For example, for a program running in Japan, getDefault creates a TimeZone object based on Japanese Standard Time.

As we can see, Pacific Time Zone on server has UTC−8:00 and Indian Standard Time on client has UTC+05:30. They differ by 13.30 and Indian date X converts to US as X-13.30 what may yield a day before on server side for certain X.

Several workarounds are possible depending on how you can influence/modify your server and client application. For example, you may work with dates in UTC+00:00 time zone on both server and client sides. If you need to show a date to the user you may convert it to Indian time zone when needed.

// Set default GMT+0:00 time zone
TimeZone timeZone;
timeZone = TimeZone.getTimeZone("GMT+0:00");
TimeZone.setDefault(timeZone);

Instead of simply using Calendar cal = Calendar.getInstance(); you may create "clear" calendar which you will user later on to set day, month and year

public static Calendar createClearedCalendar() {
    Calendar cal = Calendar.getInstance();

    cal.setTimeZone(timeZone);

    cal.set(1970, 0, 1, 0, 0, 0);
    cal.set(Calendar.HOUR_OF_DAY, 0);

    cal.clear(Calendar.MILLISECOND);

    return cal;
}

By the way, if you manipulate date-time in Java you may consider Joda Time which has more extended options and optimized performance.

Related Topic