Dimitri Dewaele
Dimitri Dewaele

Reputation: 10689

Java time: starts at 1th January 1970 at 1am?

What am I missing? Date() is the number of milliseconds that have elapsed since midnight, January 1, 1970. Should midnight not start at 0am?

References:

My test program:

package be.test.package.time;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class TimeWork {

    public static void main(String[] args) {    

        List<Long> longs = new ArrayList<>();
        List<String> strings = new ArrayList<>();

        DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss.SSS");

        //Now
        Date now = new Date();
        strings.add(formatter.format(now));

        //Test dates
        strings.add("01-01-1970 00:00:00.000");
        strings.add("01-01-1970 01:00:00.000");
        strings.add("31-11-1969 00:00:00.000");
        strings.add("01-01-2014 00:00:00.000");

        //Test data
        longs.add(-1L);
        longs.add(0L);
        longs.add(1L);
        longs.add(7260000L);
        longs.add(1417706084037L);
        longs.add(-7260000L);

        //Show the long value of the date
        for (String string: strings) {
            try {
                Date date = formatter.parse(string);
                System.out.println("Formated date : " + string + " = Long = " + date.getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        //Show the date behind the long
        for (Long lo : longs) {
            Date date = new Date(lo);
            String string = formatter.format(date);
            System.out.println("Formated date : " + string + " = Long = " + lo);        
        }
    }
}

This are the results:

Formated date : 05-12-2014 08:54:59.318 = Long = 1417766099318
Formated date : 01-01-1970 00:00:00.000 = Long = -3600000
Formated date : 01-01-1970 01:00:00.000 = Long = 0
Formated date : 31-11-1969 00:00:00.000 = Long = -2682000000
Formated date : 01-01-2014 00:00:00.000 = Long = 1388530800000
Formated date : 01-01-1970 12:59:59.999 = Long = -1
Formated date : 01-01-1970 01:00:00.000 = Long = 0
Formated date : 01-01-1970 01:00:00.001 = Long = 1
Formated date : 01-01-1970 03:01:00.000 = Long = 7260000
Formated date : 04-12-2014 04:14:44.037 = Long = 1417706084037
Formated date : 31-12-1969 10:59:00.000 = Long = -7260000

Why is:

Formated date : 01-01-1970 01:00:00.000 = Long = 0

This is at 1am. I was expecting 0am.

Upvotes: 5

Views: 7981

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 339561

The other two answers are correct.

java.time

By the way, this kind of date-time work is much easier using either the Joda-Time library or the java.time package (inspired by Joda-Time). Both of these libraries have date-time classes which have a clearly assigned time zone (unlike java.util.Date/.Calendar).

Both Joda-Time and java.time use the same epoch: 1970-01-01T00:00:00Z.

Both use the ISO 8601 standard formats when generating a textual representation of their date-time values.

Joda-Time

In Joda-Time 2.7.

DateTime epoch = new DateTime( 0 , DateTimeZone.UTC );

java.time

In java.time of Java 8 Update 45.

OffsetDateTime

The OffsetDateTime class represents a moment as seen through an offset from UTC of a certain number of hours-minutes-seconds.

OffsetDateTime epoch = OffsetDateTime.ofInstant( Instant.EPOCH , ZoneOffset.UTC ) ;

1970-01-01T00:00Z

Instant

More simply, use the constant Instant.EPOCH.

System.out.println( Instant.EPOCH.toString() ) ;

1970-01-01T00:00:00Z

ZonedDateTime

To see that that same moment through the offset used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = Instant.EPOCH.atZone( z ) ;  // Returns a `ZonedDateTime` object. 
System.out.println( zdt.toString() ) ;

We can see that at the moment of the epoch reference date-time, the people in the Americas were still in the previous year, 1969 versus 1970. Same moment, same point on the timeline, different wall-clock time.

1969-12-31T19:00-05:00[America/Montreal]

See this java.time code run live at IdeOne.com.


Table of date-time types in Java, both modern and legacy


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

Upvotes: 3

Dawood ibn Kareem
Dawood ibn Kareem

Reputation: 79876

The time represented by the long 0 is midnight 1/1/1970 UTC. This happens to be 1am 1/1/1970 CET. But since you're using a SimpleDateFormat whose timezone is set to CET,

  • 1/1/1970 1am is the time that gets displayed when you format the date;
  • parsing 1/1/1970 1am gives you the time represented by long 0.

If you had a SimpleDateFormat whose timezone was set to UTC, the behaviour would be entirely different.

You can use the setTimeZone method of DateFormat if you want to use a timezone other than CET.

Upvotes: 3

Elliott Frisch
Elliott Frisch

Reputation: 201497

January 1 1970 at midnight UTC. You need the TimeZone like

public static void main(String[] args) {
    TimeZone tz = TimeZone.getTimeZone("UTC");
    Calendar cal = Calendar.getInstance(tz);
    cal.setTimeInMillis(0);
    DateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss.SSS");
    sdf.setTimeZone(tz);
    System.out.println(sdf.format(cal.getTime()));
}

Output is

01-01-1970 12:00:00.000

Upvotes: 10

Related Questions