Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

30 minute error in Java date calculation in year 1900 only

package check;

import java.util.Calendar;

public class Test {
    public static void main(String[] args) {
        // length of a day
        long DAY_MILLIS = 1000 * 60 * 60 * 24;

        Calendar cal = Calendar.getInstance();

        cal.set(1900, 0, 1, 0, 0, 0);
        System.out.println(cal.getTime());

        cal.setTimeInMillis(cal.getTimeInMillis() + DAY_MILLIS);
        System.out.println(cal.getTime());
    }
}

And it's result is:

Mon Jan 01 00:00:00 KST 1900
Mon Jan 01 23:30:00 KST 1900 // Where is 30 minutes here?

Most funny and important clue is that this problem happens when year is 1900 only.

like image 440
jeeeyul Avatar asked May 07 '13 00:05

jeeeyul


People also ask

What can I use instead of getYear in Java?

You can get the various pieces of information with getYear , getMonth , and getDayOfMonth . You will actually get the year number with java. time! If you want a date-time instead of just a date, use ZonedDateTime class.

What can I use instead of getYear?

getFullYear() The getFullYear() method returns the year of the specified date according to local time. Use this method instead of the getYear() method.

How do you set a specific date in Java?

The setTime() method of Java Date class sets a date object. It sets date object to represent time milliseconds after January 1, 1970 00:00:00 GMT. Parameters: The function accepts a single parameter time which specifies the number of milliseconds. Return Value: It method has no return value.


2 Answers

This is because of historical GMT offset changes. See an example here http://www.timeanddate.com/worldclock/timezone.html?n=101&syear=1900. These changes are different for different time zones. For instance in my time zone (EET) the result of your test is different:

Mon Jan 01 00:00:00 EET 1900
Mon Jan 01 23:39:52 EET 1900

because (according to Java) clocks were turned forward 0:20:08 hours on 1 Jan 1900 in EET. TimeZone has methods to determine offset for a particular date, TimeZone.getOffset(long date) API

This method returns a historically correct offset value if an underlying TimeZone implementation subclass supports historical Daylight Saving Time schedule and GMT offset changes.

Note that if you set Calendar to GMT and print the result in GMT there will be no error.

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
    Calendar cal = Calendar.getInstance();
    cal.setTimeZone(TimeZone.getTimeZone("GMT"));
    cal.set(1900, 0, 1, 0, 0, 0);
    System.out.println(df.format(cal.getTime()));
    cal.setTimeInMillis(cal.getTimeInMillis() + 1000 * 60 * 60 * 24);
    System.out.println(df.format(cal.getTime()));

output

1900-01-01 00:00:00
1900-01-02 00:00:00
like image 141
Evgeniy Dorofeev Avatar answered Oct 28 '22 22:10

Evgeniy Dorofeev


Such irregularities in processing dates are common. See e.g. Jon Skeet's most famous answer. I'm looking for the actual database of these glitches; will update answer when found.

This answer is fairly incomplete but may be enough to get you unstuck; I'll leave it but encourage you to accept a more complete one if posted.

like image 45
djechlin Avatar answered Oct 28 '22 22:10

djechlin