DateFormat 解析 - 不以 UTC 返回日期 [英] DateFormat parse - not return date in UTC

查看:23
本文介绍了DateFormat 解析 - 不以 UTC 返回日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我尝试在 Android 设备上以 UTC 格式获取当前日期的 java 代码:

Here my java code that try to get current date in UTC on Android device:

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 不正确.为什么?

As you can see the dateUTCAsString IS CORRECT show current date in UTC, but after parse the dateResult is not correct. Why?

推荐答案

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

Excuse me for mentioning it, I suspect that there is no problem in your code, there’s only confusion. If you think the old Date class is behaving confusingly, allow me to be the first of many to agree with you. The good and sound solution to this problem is you stop using Date and start using the modern Java date and time API instead.

既然您正在为 Android 编码,那么第一步是获取 ThreeTenABP,这是一个提供现代 API 的 Android 库(如果您使用的是 Java 8 或 9,您可以跳过这一步,因为现代 API 将被构建在).详情在这个问题:How to use ThreeTenABP in Android Project.现在你可以这样做:

Since you are coding for Android, you first step is to get the ThreeTenABP, the library for Android that offers the modern API (if you were using Java 8 or 9, you could skip this step since the modern API wold be built in). The details are described in this question: How to use ThreeTenABP in Android Project. Now you can do:

    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);

在我的电脑上刚刚打印:

On my computer this just printed:

2017-11-15T12:54:25Z

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

The Z at the end means Zulu time zone or UTC.

您可能知道,System.out.println(dateResult) 隐式调用了 dateResult 对象的 toString 方法.类 Instant 的对象产生上述格式,始终采用 UTC,正如我所理解的那样.在大多数情况下,Instant 类是老式 Date 类的自然替代品.Instant 在内部保存自纪元以来的秒数和纳秒数,该纪元被定义为 1970 年 1 月 1 日午夜 0:00 UTC.我鼓励您将此视为无关的实现细节.Instant 是时间线上的一个点.

As you may know, System.out.println(dateResult) implicitly calls the toString method of the dateResult object. Objects of the class Instant produce the above format, always in UTC, as I understood you wanted. The Instant class is the natural replacement for the old-fashioned Date class for most purposes. Internally the Instant holds the number of seconds and nanoseconds since the epoch, which is defined as January 1 1970 at 0:00 midnight UTC. I encourage you to consider this an irrelevant implementation detail. An Instant is a point on the time-line.

出了什么问题?

您要求使用 UTC 日期.取决于你如何看待它,你可以或不能拥有它.

You asked for a date in UTC. Depending on how you look at it, you can or cannot have this.

  • 一方面,一个Date被实现为自纪元以来的秒数和毫秒数,所以如果你使用上面的纪元定义,你可能会说它是always UTC 格式.
  • 另一方面,您不必担心实现细节.从概念上讲,Date(如 Instant)是时间线上的一个点,没有也不可能有时区或偏移量;它不能在 UTC 中.更令人困惑的是,当您执行 "getCurrentDateUTC: dateResult = " + dateResult 时,会隐式调用 dateResult.toString().此方法获取 JVM 的时区设置并将日期时间转换为该时区并将其用于生成的字符串(不修改 Date 对象).这就是为什么无论您尝试打印哪个 Date,您都会在计算机或设备上看到 EET 中的时间.
  • On one hand a Date is implemented as the number of seconds and milliseconds since the epoch, so if you use the above definition of the epoch, you may say that it is always in UTC.
  • On the other hand you shouldn’t worry about implementation details. Conceptually a Date (like an Instant) is a point on the time-line, and does not and cannot have a time zone or offset; it cannot be in UTC. To make matters more confusing, when you do "getCurrentDateUTC: dateResult = " + dateResult, then dateResult.toString() is implicitly called. This method grabs your JVM’s time zone setting and converts the date-time to this zone and uses it for the generated string (without modifying the Date object). This is why you will see the time in EET on your computer or device no matter which Date you try to print.

java.time 或 JSR-310

java.time or JSR-310

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

The modern date and time API is know as java.time or JSR-310. One good source for learning to use it is the Oracle tutorial.

这篇关于DateFormat 解析 - 不以 UTC 返回日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆