【问题标题】:How to convert a date time string to long (UNIX Epoch Time) Milliseconds in Java 8 (Scala)如何在 Java 8 (Scala) 中将日期时间字符串转换为长(UNIX 纪元时间)毫秒
【发布时间】:2019-08-03 02:42:18
【问题描述】:

本题秒解:How to convert a date time string to long (UNIX Epoch Time) in Java 8 (Scala)

但如果我想要毫秒,我似乎必须使用

def dateTimeStringToEpoch(s: String, pattern: String): Long = 
    LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
      .atZone(ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0)))
      .toInstant().toEpochMilli

这对于我在另一个问题中详述的 4 个问题来说是丑陋的(我不喜欢的主要是魔法文字 "UTC" 和魔法数字 0)。

很遗憾,以下内容无法编译

def dateTimeStringToEpoch(s: String, pattern: String): Long = 
     LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
                  .toEpochMilliSecond(ZoneOffset.UTC)

因为toEpochMilliSecond 不存在

【问题讨论】:

  • ZoneOffset.UTC替换ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0))
  • @Andreas 差不多。 ZoneOffset.UTC 是ZoneOffset,所以需要将atZone 的调用改为atOffset
  • @ptomli 不是严格需要的,因为 ZoneOffsetZoneId。区别在于返回的是ZonedDateTime 还是OffsetDateTime,但由于两者都有toInstant() 方法,并且对象没有以其他方式使用,所以没有区别。
  • @Andreas 和 StackOverflow 再次教会了我一些新东西......谢谢

标签: java scala datetime java-8 epoch


【解决方案1】:

你不能用LocalDateTime#atOffsetZoneOffset#UTC吗?

LocalDateTime.parse(s, dateTimeFormatter).atOffset(ZoneOffset.UTC).toInstant().toEpochMilli()

正如@Andreas 在 cmets 中指出的那样,ZoneOffset is-a ZoneId,所以你可以使用

def dateTimeStringToEpoch(s: String, pattern: String): Long = 
    LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
      .atZone(ZoneOffset.UTC)
      .toInstant()
      .toEpochMilli()

【讨论】:

    【解决方案2】:

    在使用 UNIX Epoch 时,我建议使用 java.time.Instant,因为它是为 epoch 表示而设计的,并且默认情况下会考虑 UTC,因为它是标准的一部分。

    import java.time.Instant
    
    object InstantFormat extends App {
    
      //Instant.parse uses DateTimeFormatter.ISO_INSTANT
      println(Instant.parse("2019-03-12T15:15:13.147Z"))
      println(Instant.parse("2019-03-12T15:15:13Z"))
      println(Instant.parse("2019-03-12T15:15:13Z").toEpochMilli)
      println(Instant.parse("2019-03-12T15:15:13Z").getEpochSecond)
      println(Instant.ofEpochMilli(1552403713147L))
      println(Instant.ofEpochSecond(1552403713L))
    }
    

    输出

    2019-03-12T15:15:13.147Z
    2019-03-12T15:15:13Z
    1552403713000
    1552403713
    2019-03-12T15:15:13.147Z
    2019-03-12T15:15:13Z
    

    【讨论】:

      【解决方案3】:

      您可以更改 this answer 以返回 epoch millis 之类的

      static long dateTimeStringToEpoch(String s, String pattern) {
          return DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)
              .parse(s, Instant::from).toEpochMilli();
      }
      

      或者,如果你甚至想避免构建一个临时的Instant

      static long dateTimeStringToEpoch(String s, String pattern) {
          return DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)
              .parse(s, ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000
                             +ta.get(ChronoField.MILLI_OF_SECOND));
      }
      

      请注意,DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC)ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000+ta.get(ChronoField.MILLI_OF_SECOND) 在此处都是可重用的组件,例如你可以这样做

      static final DateTimeFormatter MY_PATTERN
          = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").withZone(ZoneOffset.UTC);
      static final TemporalQuery<Long> EPOCH_MILLIS
          = ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000+ta.get(ChronoField.MILLI_OF_SECOND);
      

      long millis = MY_PATTERN.parse("2018-07-21 18:30", EPOCH_MILLIS);
      

      问题是,您希望在您的应用程序中出现多少种不同的格式字符串。通常,它不会像您必须解析的格式化日期那样经常更改。创建从格式字符串到准备好的DateTimeFormatter 的缓存映射可能是有益的。无论如何,lambda 表达式都是一个单例。

      【讨论】:

      • 我似乎无法在 Scala 中编译,不知道如何翻译 Instant::from
      • Instant::from 等价于ta -&gt; Instant.from(ta)(TemporalAccessor ta) -&gt; Instant.from(ta)。这是一个调用static 方法Instant.from(TemporalAccessor) 的函数。在 Java 端,此函数将实现 TemporalQuery&lt;Instant&gt;,但这取决于类型推断。
      • 因为我使用的是旧的 (2.11) 版本的 Scala,所以我认为我遇到了问题,所以我必须这样做:.parse(s, new TemporalQuery[Instant] {override def queryFrom(temporal: TemporalAccessor): Instant = Instant.from(temporal)})
      猜你喜欢
      • 2019-06-18
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多