Как преобразовать строку даты и времени в длинную (UNIX Epoch Time) миллисекунды в Java 8 (Scala) - PullRequest
1 голос
/ 12 марта 2019

Этот вопрос решает случай за секунды: Как преобразовать строку даты и времени в длинную (время эпохи UNIX) в 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 не существует

Ответы [ 3 ]

5 голосов
/ 12 марта 2019

Не могли бы вы использовать LocalDateTime # atOffset и ZoneOffset # UTC ?

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

Как @Andreas указывает в комментариях, ZoneOffset is-ZoneId, чтобы вы могли использовать

def dateTimeStringToEpoch(s: String, pattern: String): Long = 
    LocalDateTime.parse(s, DateTimeFormatter.ofPattern(pattern))
      .atZone(ZoneOffset.UTC)
      .toInstant()
      .toEpochMilli()
2 голосов
/ 12 марта 2019

Вы можете изменить этот ответ , чтобы вернуть эпоху миллис, как

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. В любом случае лямбда-выражение - это одноэлементное выражение.

1 голос
/ 12 марта 2019

При работе с UNIX Epoch я предлагаю использовать java.time.Instant, так как он предназначен для представления эпох и учитывает 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
...