When I set the month on a date representing 1/1/1970, and then immediately get the month back, it's off by one.
import java.util.Date;
@Test
public void monthShouldBeExpectedValue() {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(0));
int expectedMonth = Calendar.JUNE;
calendar.set(Calendar.MONTH, expectedMonth);
int actualMonth = calendar.get(Calendar.MONTH);
assertThat(actualMonth, equalTo(expectedMonth)); // test fails: expected 5 got 6
}
If I change this line
calendar.setTime(new Date(0));
to
calendar.setTime(new Date()); // use 'today' instead of 1/1/1970
then the test passes. Anyone know why?
Edit
The printed version of the dates are:
new Date(0): Wed Dec 31 19:00:00 EST 1969
date from calendar: Tue Jul 01 19:00:00 EDT 1969
I'm running an old JDK: 1.6.0_30-b12 (64 bit)
I'm in Eastern Standard Time.
My speculation is that, due to your current timezone, the time is interpreted as December 31, 1969 + a bunch of hours. Setting month to June would therefore result in June 31, 1969 (which doesn't exist; June has 30 days). It therefore rolls over to July.
First of all, print calendar to have the exact date.
Then the usual questions:
What's your time zone?
Do you have summer savings time?
Did your time zone change since 1970?
the problem is usually that instead of midnight on the first of the month you get one hour less, i.e. late at night on the last day of the last month.
The answer by Smallhacker is correct.
For fun, I tried similar code in Joda-Time 2.3.
Same behavior, which makes sense. If you ask for a DateTime constructed from a milliseconds-from-Epoch of zero, you get start of day of January 1, 1970. But that is the date-time in UTC (no time zone offset).
If you call toString() on that DateTime object using the user's default time zone, of course you see some value other than the Epoch (start of day of January 1, 1970). Unless the user is Icelandic, where they use UTC all year round.
DateTime epoch = new DateTime( 0 );
System.out.println( "epoch: " + zero );
System.out.println( "epoch in UTC: " + zero.toDateTime( DateTimeZone.UTC ) );
When run in default time zone of west coast United States…
epoch: 1969-12-31T16:00:00.000-08:00
epoch in UTC: 1970-01-01T00:00:00.000Z
Always specify a time zone; never assume.
Working on date-time values without explicit known time zones is like working on text files without explicit known character encoding. Not smart.
To complete the answer to your question but using Joda-Time in a single line of code…
System.out.println( "June after Epoch: " + new DateTime( 0 ).toDateTime( DateTimeZone.UTC ).monthOfYear().setCopy( DateTimeConstants.JUNE ) );
When run…
June after Epoch: 1970-06-01T00:00:00.000Z
This same kind of code is smart enough to handle end-of-month. If the original were January 31, the result would be June 30.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With