#java #datetime-format
#java #datetime-формат
Вопрос:
При вызове API я получаю временную метку как: 1591290491238. Мне нужно преобразовать ее в LocalDateTime в Java. Я написал код как:
String timestamp = "1584453053825";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMdduuHHmmss");
LocalDateTime localDateTime = LocalDateTime.parse( timestamp , formatter );
Но это выдает ошибку:
Text '1584453053825' could not be parsed at index 12
Комментарии:
1. К вашему сведению,
LocalDateTime
здесь указан неправильный тип. Ваш входной номер, вероятно, представляет собой количество с момента ссылки на эпоху. Таким образом, этот ввод представляет момент, определенную точку на временной шкале. Для этого вам нуженInstant
класс.LocalDateTime
Класс не может представлять момент, поскольку в нем отсутствует какое-либо понятие часового пояса или смещения от UTC.2. @BasilBourque очень прав, не используйте
LocalDateTime
здесь (и редко используйте его вообще). Если вам нужны дата и время суток, используйтеZonedDateTime
.3. Что дал ваш поиск? Я нашел это, я думаю, это полезно: Java — Как преобразовать миллисекунды эпохи в LocalDateTime?
Ответ №1:
Число представляет время в формате Unix, то есть количество миллисекунд, прошедших с момента начала эпохи, то есть 1 января 1970 года в полночь по Гринвичу.
Вы можете преобразовать ее LocalDateTime
следующим образом:
LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(timestamp)), ZoneId.systemDefault());
Ответ №2:
Используйте ZonedDateTime для даты и времени суток
Ваша временная метка — это количество миллисекунд с эпохи Java / Unix от 1 января 1970 года в начале дня по UTC. Чтобы преобразовать его в дату и время суток, вам сначала нужно выбрать для этого часовой пояс, поскольку во всех часовых поясах никогда не бывает одного и того же времени (даже одной и той же даты). Пока число больше 1000, Java анализирует строку, содержащую его напрямую.
ZoneId zone = ZoneId.of("America/New_York");
DateTimeFormatter numericalFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS, 1, 19, SignStyle.NEVER)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter()
.withZone(zone);
String timestamp = "1591290491238";
ZonedDateTime dateTime = ZonedDateTime.parse(timestamp, numericalFormatter);
System.out.println(dateTime);
Вывод из этого фрагмента примера:
2020-06-04T13:08:11.238-04:00[Америка / New_York]
Как уже сказал Бэзил Бурк в комментарии, LocalDateTime
это неправильный класс для вашей даты и времени. ZonedDateTime
дает вам то же самое и даже больше, поскольку он также содержит часовой пояс и, следовательно, определяет момент времени, определенный исходной строкой временной метки. Вы можете преобразовать в LocalDateTime
, тем самым выбросив информацию, которую хотите сохранить. Так что делайте это только в том случае, если вам нужен LocalDateTime
API для API, разработанный людьми, которые не понимали, что это неправильный класс.
LocalDateTime amputatedDateTime = dateTime.toLocalDateTime();
System.out.println(amputatedDateTime);
2020-06-04T13:08:11.238
Вы заметили, что теперь мы потеряли смещение от UTC и часового пояса.
Что пошло не так в вашем коде?
Вы пытались проанализировать строку, используя шаблон форматирования MMdduuHHmmss
. Шаблон определяет 12 цифр, но в строке их 13. Используемый вами шаблон предполагает, что 1591290491238 относится к 12-му дню 159-го месяца 2090 года в 49:12:38 на 24-часовых часах или что-то в этом роде. Это чушь. Также потому, что, как я уже сказал, число относится к моменту времени, а не к дате и времени, и для получения последнего нам сначала нужно указать часовой пояс.
Ответ №3:
Ваша временная метка на самом деле представляет собой количество миллисекунд с 1970-01-01T00:00:00Z
момента, когда Z
обозначается Zulu
дата-время или дата-время в UTC (т. Е. Со смещением часового 00:00
пояса в часах). Вы должны разобрать ее до a long
, а затем получить Instant
из нее.
Если у вас есть объект Instant
, вы можете получить из него объекты других типов даты и времени, как показано ниже:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String timestamp = "1584453053825";
long epochMilli = Long.parseLong(timestamp);
Instant instant = Instant.ofEpochMilli(epochMilli);
// Convert instant to ZonedDateTime with the time zone of JVM
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
// Get LocalDateTime from instant
LocalDateTime ldt = zdt.toLocalDateTime();
// Display ldt in the default format i.e. the value returned by ldt#toString
System.out.println(ldt);
// Display ldt in a custom format e.g. EEE MMMM dd, uuuu hh:mm:ss a
System.out.println(ldt.format(DateTimeFormatter.ofPattern("EEE MMMM dd, uuuu hh:mm:ss a", Locale.ENGLISH)));
}
}
Вывод:
2020-03-17T13:50:53.825
Tue March 17, 2020 01:50:53 PM
Узнайте о современном API для определения даты и времени из Trail: Date Time .