2

我试着用

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDate date = LocalDate.parse(d.toString(), formatter);

但它会引发错误。

有什么方法可以转换 JSON 默认时间戳?

4

5 回答 5

6

你需要使用LocalDateTime.

DateTimeFormatter formatter = 
        DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDateTime date = LocalDateTime.parse(d.toString(), formatter);
于 2020-07-29T15:29:25.193 回答
3

您不需要DateTimeFormatter解析日期时间字符串

将给定的日期字符串直接解析为OffsetDateTime. 现代日期时间 API 基于ISO 8601DateTimeFormatter ,只要日期时间字符串符合 ISO 8601 标准,就不需要显式使用对象。您的Z日期时间字符串中的 是零时区偏移的时区指示符。它代表 Zulu 并指定Etc/UTC时区(时区偏移量为+00:00小时)。

OffsetDateTime odt = OffsetDateTime.parse("2020-12-20T00:00:00.000Z");

转换OffsetDateTimeInstant

转换OffsetDateTimeInstant使用OffsetDateTime#toInstant. AnInstant代表时间线上的一个瞬时点。它独立于时区,因此始终采用 UTC。

Instant instant = odt.toInstant();

停止使用旧的日期时间 API

随着 2014 年 3 月 Java SE 8 的发布,过时且容易出错的遗留日期时间 API(java.util日期时间类型及其格式化类型等)SimpleDateFormat现代日期时间 API *取代。强烈建议停止使用旧版 API 并切换到此新 API。如果有需要,请使用.java.timejava.util.Datejava.util.Date#from(Instant)

java.util.Date date = Date.from(instant);

请注意,该java.util.Date对象不是像现代日期时间类型那样的真实日期时间对象;相反,它表示自称为“纪元” January 1, 1970, 00:00:00 GMT(或 UTC)的标准基准时间以来的毫秒数。当您打印 的对象时java.util.Date,其toString方法会返回 JVM 时区中的日期时间,根据此毫秒值计算得出。如果您需要在不同的时区打印日期时间,则需要将时区设置为SimpleDateFormat并从中获取格式化的字符串,例如

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(date));

您可以将 a 转换Instant为其他日期时间类型

您可以Instant轻松地将其转换为其他日期时间类型,例如,如果要将其转换为ZonedDateTime表示伦敦日期时间的实例,您可以这样做

ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));

LocalDateTime在你的情况下没用

下面引用的是对 用途的非常好的描述LocalDateTime

此类可用于表示特定事件,例如美洲杯挑战者系列赛路易威登杯总决赛的第一场比赛,比赛于 2013 年 8 月 17 日下午 1:10 开始。请注意,这意味着下午 1:10在当地时间。

您的日期时间字符串的最佳用途是作为OffsetDateTime您在第一步本身中获得的。

演示:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        // Parse the date-time string into OffsetDateTime
        OffsetDateTime odt = OffsetDateTime.parse("2020-12-20T00:00:00.000Z");
        System.out.println(odt);

        // Convert OffsetDateTime into Instant
        Instant instant = odt.toInstant();

        // If at all, you need java.util.Date
        Date date = Date.from(instant);
        System.out.println(date);

        // You can convert an `Instant` to other date-time types easily
        // e.g. to ZoneDateTime in a specific timezone
        ZonedDateTime zdt = instant.atZone(ZoneId.of("Europe/London"));
        System.out.println(zdt);

        // e.g. to OffsetDateTime with a specific timezone offset
        OffsetDateTime odt0530 = instant.atOffset(ZoneOffset.of("-05:30"));
        System.out.println(odt0530);

        // e.g. to LocalDateTime via an OffsetDateTime or a ZonedDateTime
        LocalDateTime ldt = odt.toLocalDateTime();
        System.out.println(ldt);
    }
}

输出:

2020-12-20T00:00Z
Sun Dec 20 00:00:00 GMT 2020
2020-12-20T00:00Z[Europe/London]
2020-12-19T18:30-05:30
2020-12-20T00:00

Trail: Date Time了解更多关于java.time现代日期时间 API *的信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

于 2020-07-29T15:37:59.807 回答
2

Z是 Zulu 时区(即 UTC 时区),而不是文字 Z。

整个格式是 ISO-8601 即时格式。

有一个预先存在的格式化程序:DateTimeFormatter#ISO_INSTANT

从 javadoc 中提取:

公共静态最终日期时间格式化程序 ISO_INSTANT

以 UTC 格式格式化或解析瞬间的 ISO 瞬间格式化程序,例如“2011-12-03T10:15:30Z”。

这将返回一个能够格式化和解析 ISO-8601 即时格式的不可变格式化程序。格式化时,总是输出秒数。纳秒根据需要输出零、三、六或九位数字。解析时,至少需要秒字段的时间。解析从零到九的小数秒。不使用本地化的十进制样式。

这是一个特殊的格式化程序,旨在允许 Instant 的人类可读形式。Instant 类旨在仅表示一个时间点,并在内部存储从 1970-01-01Z 的固定时期开始的以纳秒为单位的值。因此,在不提供某种形式的时区的情况下,Instant 不能被格式化为日期或时间。此格式化程序允许通过使用 ZoneOffset.UTC 提供合适的转换来格式化 Instant。

格式包括:

使用 UTC 偏移量从 ChronoField.INSTANT_SECONDS 和 ChronoField.NANO_OF_SECOND 转换瞬间的 ISO_OFFSET_DATE_TIME。解析不区分大小写。

返回的格式化程序没有覆盖年表或区域。它使用 STRICT 解析器样式。

于 2020-07-29T15:38:36.747 回答
1

这似乎是默认格式,请试试这个。

ZonedDateTime dateTime  = ZonedDateTime.parse("2020-07-28T14:28:52.877Z");

// In case you still need LocalDateTime
LocalDateTime localDateTime  = dateTime.toLocalDateTime();

于 2020-07-29T15:29:13.820 回答
1

对于如何转换LocalDate为的问题java.util.Date,您可以使用Date.from以下方法。让我知道这是否是您期望实现的目标。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);
LocalDate localDate = LocalDate.parse("2020-12-20T00:00:00.000Z", formatter);
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
System.out.println(date);
于 2020-07-29T15:47:26.733 回答