为什么 string to date 和 back to string 会导致两个不同的字符串?

Why is string to date and back to string resulting in two different strings?

我的输入字符串是:

"2016-06-13T14:20:09.866Z"

我的输出字符串是:

"2016-06-13T10:20:09.866-04"

为什么它们不同,我怎样才能让它以与输入相同的格式输出?

我从字符串转换为日期:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.ENGLISH);
dateFormat.parse((String) date));

在单元测试中,我将解析的日期转换回字符串:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.ENGLISH);
dateFormat.format(date);

这两个日期相同 - 只是格式不同(一个是世界标准时间下午 2 点,另一个是上午 10 点,偏移量也是 -4 小时 = 世界标准时间下午 2 点)。

所以我想你想要的是在 UTC 时区中也有第二个字符串。在这种情况下,您可以简单地设置第二个 DateFormat 的时区:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.ENGLISH);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

Why are they different and how can I make it output in the same format as the input?

两者不仅代表同一时刻,而且格式也相同,ISO 8601.

2016-06-13T14:20:09.866Z 表示 UTC 中的日期时间。其中的 Z 是零时区偏移量的 timezone designator 。它代表祖鲁语并指定 Etc/UTC 时区(时区偏移量为 +00:00 小时)。

2016-06-13T10:20:09.866-042016-06-13T10:20:09.866-04:00 表示时区偏移 -04:00 小时的日期时间,即此时可以表示为 2016-06-13T14:20:09.866+00:002016-06-13T14:20:09.866Z在 UTC。

请注意,旧版日期时间 API(java.util 日期时间类型及其格式类型 SimpleDateFormat)已过时且容易出错。建议完全停止使用,改用java.timemodern date-time API*.

使用现代的演示 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);
    }
}

输出:

2016-06-13T10:20:09.866-04:00
2016-06-13T14:20:09.866Z

你注意到了吗,我们这里没有使用DateTimeFormatter

现代日期时间 API 基于 ISO 8601 并且不需要明确使用 DateTimeFormatter 对象,只要日期时间字符串符合 ISO 8601 标准.

Trail: Date Time[=63= 中了解有关 modern date-time API* 的更多信息].


* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用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