【问题标题】:How to convert "2020-12-20T00:00:00.000Z" to java.util.Date?如何将“2020-12-20T00:00:00.000Z”转换为 java.util.Date?
【发布时间】:2020-11-19 05:47:43
【问题描述】:

我尝试使用

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

但它会引发错误。

有没有办法转换JSON默认时间戳?

【问题讨论】:

  • 到底会抛出什么错误?
  • 如果可以避免,请不要使用java.util.Date。请改用Instant
  • 我在 Hibernate 中使用它
  • 查看此答案:stackoverflow.com/a/60214805/2513200(因为您的格式似乎符合 ISO 标准)
  • 也就是说,如果这是来自 JSON,您的 JSON 解析器库也可能为此提供函数。

标签: java date localdate datetime-parsing datetimeformatter


【解决方案1】:

您需要使用LocalDateTime

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

【讨论】:

    【解决方案2】:

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

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

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

    OffsetDateTime 转换为Instant

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

    Instant instant = odt.toInstant();
    

    停止使用旧的日期时间 API

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

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

    注意java.util.Date 对象不是像modern date-time types 那样的真实日期时间对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即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));
    

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

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

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

    LocalDateTime 在你的情况下没用

    Quoted below很好的描述了LocalDateTime的用途:

    此类可用于表示特定事件,例如 美洲杯路易威登杯总决赛的第一场比赛 挑战者系列赛于下午 1:10 开始。 2013 年 8 月 17 日。 注 这意味着下午 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
    

    了解更多关于java.timemodern date-time API* 来自Trail: Date Time


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

    【讨论】:

      【解决方案3】:

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

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

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

      从 javadoc 中提取:

      public static final DateTimeFormatter 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 解析器样式。

      【讨论】:

        【解决方案4】:

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

        ZonedDateTime dateTime  = ZonedDateTime.parse("2020-07-28T14:28:52.877Z");
        
        // In case you still need LocalDateTime
        LocalDateTime localDateTime  = dateTime.toLocalDateTime();
        
        

        【讨论】:

          【解决方案5】:

          关于如何将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);
          

          【讨论】:

            猜你喜欢
            • 2021-10-02
            • 2021-01-04
            • 2021-03-30
            • 2020-05-01
            • 1970-01-01
            • 2021-07-10
            • 1970-01-01
            • 2012-05-04
            • 1970-01-01
            相关资源
            最近更新 更多