Why does Instant.EPOCH and Timestamp.from(Instant.EPOCH) return
different results?
Echoing Stultuske's comment:
they don't, it's just the formatting that is different.
Let's see how
Given below is the hierarchy of java.sql.Timestamp
:
java.lang.Object
java.util.Date
java.sql.Timestamp
On the same page of the documentation, you will find the following information:
The inheritance relationship between Timestamp
and java.util.Date
really denotes implementation inheritance, and not type inheritance.
The implementation inheritance is a way of reusing the code of the superclass in a subclass and type inheritance is a way of specializing (subclassing) a supertype for a specific implementation**.
The purpose of creating java.sql.Timestamp
has been summarized in the following line on the same page of the documentation:
A thin wrapper around java.util.Date
that allows the JDBC API to
identify this as an SQL TIMESTAMP
value.
So, do not expect java.sql.Timestamp
to be much different from java.util.Date
.
About java.util.Date
:
A java.util.Date
object simply represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any timezone information, its toString
function applies the JVM's timezone to return a String
in the format, EEE MMM dd HH:mm:ss zzz yyyy
, derived from this milliseconds value. To get the String
representation of the java.util.Date
object in a different format and timezone, you need to use SimpleDateFormat
with the desired format and the applicable timezone e.g.
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String strDateNewYork = sdf.format(date);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDateUtc = sdf.format(date);
On the other hand, An Instant
represents an instantaneous point on the timeline in UTC.
Putting all in a demo:
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
System.out.println("Instant: " + Instant.EPOCH);
System.out.println("Timestamp: " + epochMilliFormatted());
}
public static String epochMilliFormatted() {
Date date = new Date(Timestamp.from(Instant.EPOCH).getTime());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
return sdf.format(date);
}
}
Output:
Instant: 1970-01-01T00:00:00Z
Timestamp: 1970-01-01T00:00:00Z
The Z
in the output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC
timezone (which has the timezone offset of +00:00
hours).
ONLINE DEMO
Note: The java.util
Date-Time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*. Learn more about 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.
** To learn more about the implementation inheritance and the type inheritance, check the following links:
- Multiple Inheritance of State, Implementation, and Type
- implementation inheritance vs type inheritance
- difference between interface inheritance and implementation inheritance