Why would a Date constructor with 0 long value as argument will output a date before 1970 in Java?

StackOverflow https://stackoverflow.com/questions/22669541

  •  22-06-2023
  •  | 
  •  

Question

I know they consider the epoch to be the number of milliseconds since January 1st 1970 at midnight.

However, when I set:

System.out.println(new Date(0));

I get:

Wed Dec 31 18:00:00 CST 1969

As it'd go backwards, why?

Silly edit:

Yes, I'm at GMT -6

Was it helpful?

Solution

The epoch starts at January 1st, 1970, at midnight UTC. Your system default timezone is probably 6 hours off of UTC at that time. (This is why functions that use system defaults without making that choice explicit are bad.)

OTHER TIPS

The java.util.Date object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value.

Since your JVM's timezone offset is -06:00 hours, January 1, 1970, 00:00:00 GMT is being displayed as Wed Dec 31 18:00:00 CST 1969. If you need to print the date-time in GMT (or UTC), you will need to set the corresponding timezone to SimpleDateFormat and obtain the formatted string from it e.g.

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Date date = new Date(0);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
        sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        System.out.println(sdf.format(date));
    }
}

Output:

1970-01-01T00:00:00.000Z

With the release of Java SE 8 (March 2014), the outdated and error-prone legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat etc.) was supplanted by java.time, the modern date-time API*.

Using java.time, the modern API:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.EPOCH;
        System.out.println(instant);

        // Alternatively,
        instant = Instant.ofEpochMilli(0);
        System.out.println(instant);

        // The same instant in your JVM's timezone
        ZonedDateTime zdt = instant.atZone(ZoneId.of("America/Mexico_City"));
        System.out.println(zdt);
    }
}

Output:

1970-01-01T00:00:00Z
1970-01-01T00:00:00Z
1969-12-31T18:00-06:00[America/Mexico_City]

Instant represents an instantaneous point on the timeline. The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

Learn more about java.time, the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top