How to convert a date time string to long (UNIX Epoch Time) Milliseconds in Java 8 (Scala)

故事扮演 提交于 2019-12-08 07:54:59

问题


This question solves the case for seconds: How to convert a date time string to long (UNIX Epoch Time) in Java 8 (Scala)

But if I want milliseconds it seems I have to use

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

which is ugly for the 4 issues I detail in the other question (main things I don't like is the magic literal "UTC" and the magic number 0).

Unfortunately the following does not compile

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

as toEpochMilliSecond does not exist


回答1:


Could you not use LocalDateTime#atOffset and ZoneOffset#UTC?

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

As @Andreas points out in the comments, ZoneOffset is-a ZoneId, so you could use

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



回答2:


You can change this answer to return epoch millis like

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

Or, if you even want to avoid the construction of a temporary 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));
}

Note that both, DateTimeFormatter.ofPattern(pattern).withZone(ZoneOffset.UTC) and ta -> ta.getLong(ChronoField.INSTANT_SECONDS)*1000+ta.get(ChronoField.MILLI_OF_SECOND) are reusable components here, e.g. you could do

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);

and

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

The question is, how many different format strings do you expect to occur within you application. Usually, it’s not something that changes as often as the formatted dates you have to parse. It might be beneficial to create a cache mapping from format string to prepared DateTimeFormatter. The lambda expression is a singleton anyway.




回答3:


When working with UNIX Epoch, I suggest using java.time.Instant as it designed for epoch representation and takes UTC into consideration by default, as it is part of the standard.

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))
}

outputs

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


来源:https://stackoverflow.com/questions/55124653/how-to-convert-a-date-time-string-to-long-unix-epoch-time-milliseconds-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!