tags:

views:

488

answers:

5

I use the following code:

Calendar calendar = new GregorianCalendar(0,0,0);
calendar.set(Calendar.YEAR, 1942);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.DAY_OF_MONTH, 4);

Date date1 = calendar.getTime();

calendar.add(Calendar.DAY_OF_MONTH, -1);

Date date2 = calendar.getTime();

System.out.println(date1 + "\n" + date2);

This code output follows:

Sat Apr 04 00:00:00 EEST 1942
Fri Apr 03 01:00:00 EEST 1942

Actually I subtract 1 day and time should be preserved. But why second line of output contains 1 hour in the time while it should be 0?

EDIT:

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

+1  A: 

Are you using the latest java-version? Check that, because on my java installation (1.6.0_16) it works fine, output is:

Sat Apr 04 00:00:00 GMT 1942
Fri Apr 03 00:00:00 GMT 1942

Sun usually update the time-zone-database on the java-updates, so check you are using the latest version!

Or, other thing:

Perhaps it has something to do with daylight saving? The US government introduced Daylight Saving in the WWII-years, this could be the cause in your timezone but not in mine?

theomega
1. He is not in a USA time zone. 2. DST was introduced in the USA decades prior to WWII. 3. There was no DST even in the USA in 1942, exactly, the entire year was timeshifted.
DigitalRoss
the code works fine for me too...so check the version, timezone etc
Vincent Ramdhanie
A: 

The result you get may well depend on the timezone in which you run the code. In your local time zone, that 1 day interval might span a change in daylight savings time, or some other one-off clock adjustment for your country / region.

serg10
+2  A: 

It looks like the library is taking a guess at "Summer Time"

It may be hard to define "the right answer" for what you are doing. Eastern European Summer Time did not exist in 1942. Even in the USA where the library code may have been written there was no DST that year, as the War Time Act of 1942 made that entire year timeshifted.

The usual answer on SO to problems with Java dates and times is to use Joda Time. I'm not sure that would help here, but it might.

My guess is that the program is applying the DST shift incorrectly, or simply taking a best guess at what it might have been, had EEST existed in 1942.

DigitalRoss
@DigitalRoss - just tested this with Joda as DateTime c2 = new DateTime(DateTimeZone.forID("Europe/Helsinki")).withYear(1942).withMonthOfYear(4).withDayOfMonth(4).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0); and then .minusDays(1), same problem. +1 for your hypothesis
fvu
+14  A: 

I suppose you are using a Finnish timezone. In Finland, daylight saving time was introduced in 1942 by adjusting the clock from April 2nd, 23:59:59 to April 3rd, 1:00:00. The time span April 3rd, 0:00:00 to 0:59:59 did not exist, so the Java Calendar makes a best effort result.

jarnbjo
In Fact the EEST which he uses is used for Finland, so your answer seems to be the right solution +1
theomega
It looks like it is. I use Europe/Helsinki timezone, I updated post.
sergdev
I didn't check this, but the answer looks reasonable for me. Thanks! VThe bad thing is I need to iterate on dates, find distance between date etc... I am not interesting in time at all! I decided to write it by hand. I don't want to use Joda because I am writing applet and don't want to make user download Joda included every time. Moreover I didn't use Joda, but it looks like from fvu's comment it doesn't resolve the problem.
sergdev
A: 

I'll write another answer to serdev's comment, since it's a little bit difficult to include much information in a comment alone.

You say that you have to iterate over dates and find distances and if you make some assumptions, which have to be valid for your locale or timezone, this isn't too difficult. If you ignore the time and use your code to subtract one day from "Sat Apr 04 1942", you get "Fri Apr 03 1942" as expected. If you need to find the number of days between to dates, I would calculate it myself:

// set two Calendars to April 1st, 1942 and April 5th, 1942 (both 0:00)
Calendar cal1 = new GregorianCalendar(1942, 3, 1);
Calendar cal2 = new GregorianCalendar(1942, 3, 5);

// divide the difference in ms by the number of ms in 24 hours and round the result
long diff = Math.round((cal2.getTimeInMillis() - cal1.getTimeInMillis()) / (24.*60*60*1000));

Just dividing would with a Finnish time zone give a difference of 3.958 days, but rounding it gives a correct 4 days result.

For this to work, you must however assume that dates are continuous and that your time zone does not change by more than 11 hours between the start and end date. This is not always true, since there have been some cases of nations around the international date line to 'switch side'. The most recent case was when parts of Kiribati skipped December 31st 1994 to have the entire country on one side of the date line. Before the change, the nation's time zones only span a few hours, but because it was split by the date line, the country had in reality two different dates.

jarnbjo
Possibly this works, but I have already implemented precise solution without using time at all, only dates. Actually I would not like to stuck again because of some other unexpected surprises, e.g. leap seconds or something other. Much more easy and robust to implement function getDateIndex(year,month,day) {approx. return (year-1) * 4 - (year-1) * 100 + (year-1) * 400 + number of days from year start for (month,day)}
sergdev