【问题标题】:How to parse JSR-310 date to Instant?如何将 JSR-310 日期解析为 Instant?
【发布时间】:2020-05-27 11:53:08
【问题描述】:

我正在尝试使用 JSR-310 时间解析 "2020-01-12+01:00"

我通过 DateTimeFormatter.ofPattern("yyyy-MM-ddVV") 阅读它,但是现在如果我想通过 Instant.from(DateTimeFormatter.ofPattern("yyyy-MM-ddVV").parse("...") 将其转换为 Instant,它会在抱怨 time 为空的地方抛出。

这是理所当然的,但是,我想从中获得 Instant,即 epochMillis,所以我可以将 long 序列化到数据库中。

有办法解决吗?基本上我想将"2020-01-12+01:00" 扩展到"2020-01-12T00:00.000+01:00" 并像往常一样将其解析为 Instant

【问题讨论】:

  • 你总是想要午夜的瞬间,在指定的时间偏移?
  • 你的模式可以简单地是DateTimeFormatter.ISO_DATE吗?
  • @DawoodsaysreinstateMonica 是的
  • @LairdNelson 我试过了,但不管出于什么原因它给了我zone=null;但如果我使用自己的模式,它会起作用,我做错了吗?
  • 我认为答案是DateTimeFormatter.ofPattern("yyyy-MM-ddVV").parse("...", Instant::from),但我目前无法对此进行测试。

标签: java java-time date-parsing jsr310 java.time.instant


【解决方案1】:

只要你知道怎么做就很容易了。我们需要的格式化程序是内置的。有一个复杂的事实是没有将字符串解析成的类型,没有OffsetDate。我提出了两种解决方案。

    String s = "2020-01-12+01:00";

    TemporalAccessor parsed = DateTimeFormatter.ISO_OFFSET_DATE.parse(s);
    LocalDate date = LocalDate.from(parsed);
    ZoneOffset offset = ZoneOffset.from(parsed);
    Instant result = date.atStartOfDay(offset).toInstant();

    System.out.println(result);

这个 sn-p 的输出是:

2020-01-11T23:00:00Z

我们很少需要直接使用TemporalAccessor接口,它被认为是低级的。这也不是去这里的唯一途径。另一个不错的选择是定义一个默认时间,这样我们就可以直接解析为Instant

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_OFFSET_DATE)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .toFormatter();
    Instant result = formatter.parse(s, Instant::from);

结果和之前一样。

【讨论】:

    【解决方案2】:

    您需要使用DateTimeFormatterBuilder,指定ISO_DATE 格式和default 时间(午夜1):

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_DATE)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .toFormatter();
    Instant instant = Instant.from(formatter.parse("2020-01-12+01:00"));
    System.out.println(instant);
    

    1) ChronoField 可以是任何时间-一天中 字段,即HOUR_OF_DAYCLOCK_HOUR_OF_DAYMINUTE_OF_DAYSECOND_OF_DAY、@ 987654335@、MICRO_OF_DAYNANO_OF_DAY

    输出

    2020-01-11T23:00:00Z
    

    如果要保留时区偏移,需要使用OffsetDateTime(或ZonedDateTime)代替Instant

    OffsetDateTime dateTime = OffsetDateTime.parse("2020-01-12+01:00", formatter);
    System.out.println(dateTime);
    System.out.println(dateTime.format(DateTimeFormatter.ISO_DATE));
    

    输出(来自 OffsetDateTime 和 ZonedDateTime)

    2020-01-12T00:00+01:00
    2020-01-12+01:00
    

    【讨论】:

      【解决方案3】:

      您可以使用LocalDate.parse(dateString, formatter) 使用上面创建的Formatter 为您提供LocalDate 实例。

      LocalDate 可以在当天的任何时间给你一个LocalDateTime,但是(例如)你可以从它那里得到the start of day

      LocalDateTime 有一个toInstant 方法可以给你一个Instant

      Instant 有一个toEpochMilli 方法来获取您的long

      【讨论】:

      • 我认为这不是一个好主意。你最终会丢弃偏移量。
      • 公平。 ZonedDate* 方法相同,观察偏移量。
      猜你喜欢
      • 1970-01-01
      • 2015-07-18
      • 2015-02-11
      • 2020-10-21
      • 1970-01-01
      • 2018-01-09
      • 2014-07-21
      • 1970-01-01
      相关资源
      最近更新 更多