Преобразование строки в мгновенное - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь преобразовать дату и время в строку в момент, используя java 8 или пакет утилит.

Например,

String requestTime = "04:30 PM, Sat 5/12/2018";

в

Instant reqInstant should result in 2018-05-12T20:30:00.000Z

reqString isв Америке / часовой пояс Торонто.

Это то, что я пробовал

 String strReqDelTime = "04:30 PM, Sat 5/12/2018";
 Date date = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy").parse(requestTime);
 Instant reqInstant = date.toInstant();

Приведенный выше код приводит к "2018-05-12T23:30:00Z".

Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Похоже, что часовой пояс на вашем компьютере (сервере) соответствует тихоокеанскому летнему времени США (GMT-7), но вы ожидаете, что результат будет для восточного летнего времени США (GMT-4).

Instant.toString () возвращает UTC (GMT + 0) DateTime в формате ISO-8601. («Z» в конце означает UTC).

SimpleDateFormat угрожает DateTime String в часовом поясе компьютера по умолчанию, если он не указан. И ваш ввод не указывает часовой пояс.

Итак, вам нужно что-то сделать с тем, в каком часовом поясе вы вводите.

PS. на моей машине в восточном DST ваш код дает мне результат в точности так, как вы ожидали.

0 голосов
/ 12 мая 2018

ТЛ; др

  • Исправьте ваш шаблон форматирования для незаполненного месяца и дня.
  • Используйте только java.time классы, но не устаревшие классы.

Придуманный пример:

LocalDateTime.parse(                   // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.
    "04:30 PM, Sat 5/12/2018" ,        // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the java.time classes use the standard formats by default when parsing/generating strings.
    DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US )  // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values.
)                                      // Returns a `LocalDateTime` object.
.atZone(                               // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.
    ZoneId.of( "America/Toronto" )     // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`. 
)                                      // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto].
.toInstant()                           // Extract a `Instant` object, always in UTC by definition.
.toString()                            // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*.

2018-05-12T20: 30: 00Z

Использовать шаблон форматирования из одной цифры

Вы использовали MM в шаблоне форматирования, чтобы означать, что любое однозначное значение (месяцы январь-сентябрь) будет отображаться с добавленным начальным нулем.

Но вашему вводу не хватает того начального нуля. Так что используйте один M.

То же самое для дня месяца, который я ожидаю: d вместо dd.

Использовать только java.time

Вы используете проблемные старые классы даты и времени (Date & SimpleDateFormat), которые были вытеснены несколько лет назад классами java.time . Новые классы полностью вытесняют старые. Не нужно смешивать наследие и современность.

LocalDateTime

Анализировать как LocalDateTime, поскольку во входной строке отсутствует индикатор часовой пояс или смещение от UTC . Такое значение не момент, не точка на временной шкале. Это всего лишь набор потенциальных моментов в диапазоне около 26-27 часов.

String input = "04:30 PM, Sat 5/12/2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US );  // Specify locale to determine human language and cultural norms used in translating that input string.
LocalDateTime ldt = LocalDateTime.parse( input , f );

ldt.toString (): 2018-05-12T16: 30

ZonedDateTime

Если вы точно знаете, что ввод был предназначен для представления момента с использованием настенных часов, используемых жителями региона Торонто, Канада, примените ZoneId, чтобы получить объект ZonedDateTime .

Назначение часового пояса придает смысл вашему незонированному LocalDateTime. Теперь у нас есть момент, точка на временной шкале.

ZoneId z = ZoneId.of( "America/Toronto" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;  // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline.

zdt.toString (): 2018-05-12T16: 30-04: 00 [Америка / Торонто]

Instant

Чтобы увидеть тот же момент, что и UTC , извлеките Instant. В тот же момент, разное время настенных часов.

Instant instant = zdt.toInstant() ;

instant.toString (): 2018-05-12T20: 30: 00Z


О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

...