java - DateFormat 解析 - 不返回 UTC 格式的日期

标签 java android datetime utc date-parsing

这里是我的 java 代码,它尝试在 Android 设备上获取当前 UTC 日期:

public static Date getCurrentDateUTC() {
    try {
        TimeZone timeZoneUTC = TimeZone.getTimeZone("UTC");
        Date localTime = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss Z");
        dateFormat.setTimeZone(timeZoneUTC);
        String dateUTCAsString = dateFormat.format(localTime);
        Debug.d(TAG, "getCurrentDateUTC: dateUTCAsString = " + dateUTCAsString);
        Date dateResult = dateFormat.parse(dateUTCAsString);
        Debug.d(TAG, "getCurrentDateUTC: dateResult = " + dateResult);
        return dateResult;
    } catch (ParseException e) {
        Debug.e(TAG, "getCurrentDateUTC: ", e);
        return null;
    }
}

结果:

dateUTCAsString = 2017-11-15T12:54:25 +0000
dateResult = Wed Nov 15 14:54:25 EET 2017

如您所见,dateUTCAsString 是正确的,以 UTC 格式显示当前日期,但在 parse 后,dateResult 不正确。为什么?

最佳答案

不好意思提一下,我怀疑你的代码没有问题,只是困惑。如果您认为旧的 Date 类的行为令人困惑,请允许我成为第一个同意您观点的人。解决此问题的最佳方法是停止使用 Date 并开始使用现代 Java 日期和时间 API。

由于您正在为 Android 编码,因此第一步是获取 ThreeTenABP,这是一个提供现代 API 的 Android 库(如果您使用的是 Java 8 或 9,您可以跳过此步骤,因为现代 API 将会构建)在)。详情参见 this question: How to use ThreeTenABP in Android Project 。现在您可以执行以下操作:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss Z");
    String dateUTCAsString = "2017-11-15T12:54:25 +0000";
    Instant dateResult = OffsetDateTime.parse(dateUTCAsString, formatter).toInstant();
    System.out.println(dateResult);

在我的计算机上刚刚打印:

2017-11-15T12:54:25Z

末尾的 Z 表示祖鲁时区或 UTC。

正如您所知,System.out.println(dateResult) 隐式调用 dateResult 对象的 toString 方法。 Instant 类的对象生成上述格式,始终采用 UTC,正如我理解您想要的那样。对于大多数用途来说,Instant 类是老式 Date 类的自然替代品。在内部,Instant 保存自纪元(定义为 UTC 时间 1970 年 1 月 1 日午夜 0:00)以来的秒数和纳秒数。我鼓励您将其视为不相关的实现细节。 瞬间是时间线上的一个点。

出了什么问题?

您询问了 UTC 日期。你可以或不能拥有它,取决于你如何看待它。

  • 一方面,Date 被实现为自纪元以来的秒数和毫秒数,因此,如果您使用上述纪元定义,您可能会说它总是 采用 UTC 时间。
  • 另一方面,您不必担心实现细节。从概念上讲,Date(如Instant)是时间线上的一个点,没有也不可能有时区或偏移量;它不能是 UTC。更令人困惑的是,当您执行 "getCurrentDateUTC: dateResult = "+ dateResult 时,会隐式调用 dateResult.toString() 。此方法获取 JVM 的时区设置,并将日期时间转换为该时区,并将其用于生成的字符串(无需修改 Date 对象)。这就是为什么无论您尝试打印哪个日期,您都会在计算机或设备上看到 EET 时间。

java.time 或 JSR-310

现代日期和时间 API 称为 java.time 或 JSR-310。学习使用它的一个很好的来源是 the Oracle tutorial .

关于java - DateFormat 解析 - 不返回 UTC 格式的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47307909/

相关文章:

java - 在 spring 中并行调用不同的方法

java - 多线程使用中的变量声明,Java [内存泄漏问题]

java - 将 Java 对象转换为 Xml,反之亦然

java - 将存储在 SQLite 数据库中的经度和纬度数据导出到文件以便可以通过网站将其导入 Google Map API 的最简单方法?

python - Python 中日期之间的平均差异

python - 如何合并 pandas 列和合并日期时间

javascript - 如何在 dmy 格式的日期之间循环

java - 如何使用 Smack XMPP 库创建 SSL 连接?

java - Android:以编程方式在新 Activity 中创建线性布局

java - 在Android中获取当月的最后一个时间戳