Nathan Spears
Nathan Spears

Reputation: 1667

Java.util.Calendar - milliseconds since Jan 1, 1970

Program followed by output. Someone please explain to me why 10,000,000 milliseconds from Jan 1, 1970 is November 31, 1969. Well, someone please explain what's wrong with my assumption that the first test should produce a time 10,000,000 milliseconds from Jan 1, 1970. Numbers smaller than 10,000,000 produce the same result.

public static void main(String[] args) {

    String x = "10000000";
    long l = new Long(x).longValue();
    System.out.println("Long value: " + l);

    Calendar c = new GregorianCalendar();
    c.setTimeInMillis(l);
    System.out.println("Calendar time in Millis: " + c.getTimeInMillis());

    String origDate = c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH);  
    System.out.println("Date in YYYY-MM-DD format: " + origDate);

    x = "1000000000000";
    l = new Long(x).longValue();
    System.out.println("\nLong value: " + l);

    c.setTimeInMillis(l);
    System.out.println("Calendar time in Millis: " + c.getTimeInMillis());

    origDate = c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH);  
    System.out.println("Date in YYYY-MM-DD format: " + origDate);
}

Long value: 10000000

Calendar time in Millis: 10000000

Date in YYYY-MM-DD format: 1969-11-31

Long value: 1000000000000

Calendar time in Millis: 1000000000000

Date in YYYY-MM-DD format: 2001-8-8

Upvotes: 8

Views: 39742

Answers (6)

Steve McLeod
Steve McLeod

Reputation: 52468

First, c.get(Calendar.MONTH) returns 0 for Jan, 1 for Feb, etc.

Second, use DateFormat to output dates.

Third, your problems are a great example of how awkward Java's Date API is. Use Joda Time API if you can. It will make your life somewhat easier.

Here's a better example of your code, which indicates the timezone:

public static void main(String[] args) {

    final DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);

    long l = 10000000L;
    System.out.println("Long value: " + l);
    Calendar c = new GregorianCalendar();
    c.setTimeInMillis(l);
    System.out.println("Date: " + dateFormat.format(c.getTime()));

    l = 1000000000000L;
    System.out.println("\nLong value: " + l);
    c.setTimeInMillis(l);
    System.out.println("Date: " + dateFormat.format(c.getTime()));
}

Upvotes: 6

Alexander
Alexander

Reputation: 9370

Your timezone is most likely lagging behind GMT (e.g., GMT-5), therefore 10,000,000ms from epoch is December 31 1969 in your timezone, but since months are zero-based in java.util.Calendar your Calendar-to-text conversion is flawed and you get 1969-11-31 instead of the expected 1969-12-31.

Upvotes: 1

Julien Chastang
Julien Chastang

Reputation: 17784

Sadly, java.util.Date and java.util.Calendar were poorly designed leading to this sort of confusion.

Upvotes: 4

Mike
Mike

Reputation: 1594

Calendar#setTimeInMillis() sets the calendar's time to the number of milliseconds after Jan 1, 1970 GMT.

Calendar#get() returns the requested field adjusted for the calendar's timezone which, by default, is your machine's local timezone.

This should work as you expect if you specify "GMT" timezone when you construct the calendar:

Calendar c = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

Upvotes: 5

C. K. Young
C. K. Young

Reputation: 223133

The dates you print from Calendar are local to your timezone, whereas the epoch is defined to be midnight of 1970-01-01 in UTC. So if you live in a timezone west of UTC, then your date will show up as 1969-12-31, even though (in UTC) it's still 1970-01-01.

Upvotes: 13

Davide
Davide

Reputation: 17828

You can figure out yourself if you change your first c.setTimeInMillis(l); in c.clear();

Upvotes: 0

Related Questions