Why are they different and how can I make it output in the same format
as the input?
Both of them not only represent the same moment but are also in the same format, ISO 8601.
2016-06-13T14:20:09.866Z
represents a date-time in UTC. The Z
in it 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).
2016-06-13T10:20:09.866-04
or 2016-06-13T10:20:09.866-04:00
represents a date-time at a timezone offset of -04:00
hours i.e. this moment can be represented as 2016-06-13T14:20:09.866+00:00
or 2016-06-13T14:20:09.866Z
in UTC.
Note that the legacy date-time API (java.util
date-time types and their formatting type, SimpleDateFormat
) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time
, the modern date-time API*.
Demo using the modern API:
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class Main {
public static void main(String[] args) {
OffsetDateTime odtWithMinusFourHoursOffset = OffsetDateTime.parse("2016-06-13T10:20:09.866-04");
System.out.println(odtWithMinusFourHoursOffset);
OffsetDateTime odtWithSameMomentInUtc = odtWithMinusFourHoursOffset.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println(odtWithSameMomentInUtc);
}
}
Output:
2016-06-13T10:20:09.866-04:00
2016-06-13T14:20:09.866Z
Did you notice, we did not use DateTimeFormatter
here?
The modern date-time API is based on ISO 8601 and does not require using a DateTimeFormatter
object explicitly as long as the date-time string conforms to the ISO 8601 standards.
Learn more about the 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.