views:

367

answers:

4

I want to represent midnight by java.util.Date class. To check this I output this value and obtain unexpected result.

The code follows:

Calendar calendar = new GregorianCalendar(1921, 4, 1, 0, 0);
Date date2 = calendar.getTime();
System.out.println(date2);

I obtain the following output:

Sun May 01 00:20:08 EET 1921

But I expect to obtain

Sun May 01 00:00:00 EET 1921

What is the cause of such behavior?

Currently I am testing my code in Europe/Helsinki timezone.

+9  A: 

Why don't you simply check the time zone history for your country? You asked a similar question just a few days ago. Finland had a very odd time zone GMT+1:39:52 until April 30th, 1921. From May 1st, they switched to GMT+2:00 and jumped from 23:59:59 to 00:20:08.

jarnbjo
sergdev
+1:39:52?? WTF? And even more amazing - the library takes it into account correctly!
Michael Burr
+1 for obscure reference knowledge - I am amazed that it takes it into account! :)
aperkins
+1, but note that the answer comes across a little harsh; if any of the 3 countries I have lived in had such an obscure historical occurrence I would not have known.
Software Monkey
Most countries or regions had "odd" time zones until standard time zones based on full or rarely half/quarter hours off Greenwich was introduced mostly between 1850 and 1900, so this is not really obscure at all. Even London itself was 1 minute and 15 seconds before GMT until 1847. New York City was on -4:56:02 until 1883.
jarnbjo
Of course... that makes sense when you think about it for a minute. Or minute 15 seconds.
Michael Burr
+3  A: 

Luckily I still had my test code from last time handy ;-)

public static void main(String[] args) {
    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Europe/Helsinki"));
    calendar.set(1921,4, 1, 0, 0);
    Date date2 = calendar.getTime();
    System.out.println("GregorianCalendar: " + date2);

    DateTime c2 = new DateTime(DateTimeZone.forID("Europe/Helsinki")).withYear(1921).
            withMonthOfYear(5).withDayOfMonth(1).withHourOfDay(0). withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
    System.out.println("Joda: " + c2);
}

gives

GregorianCalendar: Sat Apr 30 23:20:43 CEST 1921
Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 0 for minuteOfHour is not supported: Illegal instant due to time zone offset transition: 1921-05-01T00:00:35.781 (Europe/Helsinki)
    at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469)
    at org.joda.time.DateTime.withMinuteOfHour(DateTime.java:1485)
fvu
Thanks! actually I from my previous questions I have not understood how to manage time surprises, but now all is clear for me.In future problems I will refer to http://www.timeanddate.com/ for history.
sergdev
A: 

Upvote to jarnbjo above, would Joda-Time help any of your problems?

The Java Date/Time/Calendar libraries are a bit broken at times.

Dean J
When it comes to time zones, Joda uses the same source as the JDK (the time zone database from http://www.twinsun.com/tz/tz-link.htm), but if you use Joda, you have to make sure that your Joda library is updated with a current database in addition to the JDK.
jarnbjo
+1  A: 

Actually lots of time-zones give strange result before Oct 1979. I suggest you look at Joda-time if you want accurate historical time zones.

The worst day appears to be 1 Jan 1900 for some reason. Try

Calendar calendar = new GregorianCalendar(1900, 1, 1, 0, 0);
Date date2 = calendar.getTime();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
System.out.println("Time in UTC is " + date2);

for (String tz : TimeZone.getAvailableIDs()) {
    TimeZone.setDefault(TimeZone.getTimeZone(tz));
    String dateToString = date2.toString();
    if (dateToString.contains(":00:00")) continue;
    if (dateToString.contains(":30:00")) continue;
    System.out.println(tz + ' ' + dateToString);
}

Before 1900, very few timezones produce these sort of results (perhaps these are the inaccurate ones)

Peter Lawrey