【问题标题】:Instant.now equivalent to java.util.Date or Java 7Instant.now 等效于 java.util.Date 或 Java 7
【发布时间】:2019-05-19 23:36:41
【问题描述】:

我有一个使用 Java 7 的系统,我需要生成一个与 Instant.now (Java 8) 等效的日期。

例如,Instant.now().toString() 生成这样的日期: “2018-12-19T12:32:46.816Z”

使用java.util.Date 我有这个日期:"2018-12-19T10:38:13.892"

    Date date = new Date(System.currentTimeMillis());
    SimpleDateFormat sdf;
    sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
    String text = sdf.format(date);
    System.out.println(text);

我不知道我是否可以在这个日期的末尾简单地连接一个 "Z"

如果没有 "Z",另一个使用 Instant.parse 解析此日期的系统会引发错误:

java.time.format.DateTimeParseException:文本 '2018-12-19T10:38:13.892' 无法在索引 23 处解析 在 java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988) 在 java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1890) 在 java.base/java.time.Instant.parse(Instant.java:395)

【问题讨论】:

  • 你考虑过ThreeTen Backport吗? java.time 是现代 Java 日期和时间 API,已向后移植到 Java 6 和 7。
  • java.util.Date 本身没有时区(Z 代表的地方),所以你必须添加它。例如格式:sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
  • @Glains 实际上,Z 代表 UTC,表示与 UTC 的偏移量为零时分秒,不是时区。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。 java.util.Datejava.time.Instant 一样,表示 UTC 中的一个时刻,因为它只是自 1970 年 UTC 第一时刻的纪元参考以来的一个计数。 Date 是自 1970-01-01T00:00:00Z 以来的毫秒数,Instant 是纳秒数,根据定义,两者都代表 UTC 中的时刻

标签: java datetime java-8 java-7 datetime-format


【解决方案1】:

Z 表示UTC time zone,您可以将时区设置为UTC 并手动附加Z

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

【讨论】:

  • 这确实可能是正确的答案 - 当日期已经是 UTC 时。可能是这种情况。
  • @JoopEggen 一个老式的Date 不在任何特定的时区,它只是一个时间点。
  • @OleV.V.是的,我的评论是为了指出 Z 是 java >8 中 UTC 时区的结果。
  • 您可以指定X,而不是硬编码的'Z',以插入实际的时区,当setTimeZone(TimeZone.getTimeZone("UTC"))被正确指定时,这将导致Z
  • 仅供参考,非常麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 中内置的 java.time 类所取代,之后。见Tutorial by Oracle
【解决方案2】:

ThreeTen 反向移植

java.time,现代 Java 日期和时间 API,已被向后移植。所以就像在 Java 8 中一样:

    String text = Instant.now().toString();

刚刚运行我得到了:

2018-12-19T13:37:37.186Z

  • 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

过时的 SimpleDateFormat

如果您在迁移到 Java 8 或更高版本之前不想依赖外部依赖项,那么(最)正确的解决方案是其他两个答案的组合(其中一个现已删除):

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXX");
    sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
    String text = sdf.format(System.currentTimeMillis());

2018-12-19T13:37:37.285Z

它并不总是给出与Instant.toString 完全相同的字符串,但它会给出一个Instant 可以在其他系统中解析的字符串。虽然Instant.toString() 只打印所需数量的小数,但上面的SimpleDateFormat 也会打印三个小数,其中一些是0

当格​​式化程序的时区为 UTC 时,格式化模式字母(大写)X 将把 Z 打印为“时区”(实际上只是一个偏移量)。

链接

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    • 2017-11-13
    • 1970-01-01
    • 2020-03-31
    相关资源
    最近更新 更多