Java-синтаксический анализ даты с точностью до микросекунды или наносекунды - программирование

Java-синтаксический анализ даты с точностью до микросекунды или наносекунды

Согласно документации класса SimpleDateFormat, Java не поддерживает временную детализацию выше миллисекунд в своих шаблонах дат.

Итак, строка даты, например

  • 2015-05-09 00: 10: 23.999750900//Последние 9 цифр обозначают наносекунды.

при анализе с помощью шаблона

  • yyyy-MM-dd HH: mm: ss.SSSSSSSSS//9 'S' символы

фактически интерпретирует все число после символа . как (почти 1 миллиард!) миллисекунд, а не как наносекунды, в результате чего дата

  • 2015-05-20 21:52:53 UTC

то есть. на 11 дней вперед. Удивительно, но использование меньшего количества символов S по-прежнему приводит к анализу всех 9 цифр (вместо, скажем, самого левого 3 для .SSS).

Есть два способа правильно решить эту проблему:

  • Использовать предварительную обработку строк
  • Используйте обычную реализацию SimpleDateFormat

Будет ли другой способ получить правильное решение, просто поставляя шаблон стандартной реализации SimpleDateFormat без каких-либо других модификаций кода или строковых манипуляций?

4b9b3361

Ответ 1

ТЛ; др

LocalDateTime.parse(                 // With resolution of nanoseconds, represent the idea of a date and time somewhere, unspecified. Does *not* represent a moment, is *not* a point on the timeline. To determine an actual moment, place this date+time into context of a time zone (apply a 'ZoneId' to get a 'ZonedDateTime'). 
    "2015-05-09 00:10:23.999750900"  // A 'String' nearly in standard ISO 8601 format.
    .replace( " " , "T" )            // Replace SPACE in middle with 'T' to comply with ISO 8601 standard format.
)                                    // Returns a 'LocalDateTime' object.

Нету

Нет, вы не можете использовать SimpleDateFormat для обработки наносекунд.

Но ваша предпосылка, что...

Java не поддерживает детализацию времени свыше миллисекунд в своих шаблонах дат

… Больше не относится к Java 8, 9, 10 и более поздним версиям со встроенными классами java.time. И не совсем верно для Java 6 и Java 7, так как большая часть функциональности java.time перенесена обратно.

java.time

SimpleDateFormat и связанные с ним классы java.util.Date/.Calendar теперь устарели из-за нового пакета java.time, доступного в Java 8 (Tutorial).

Новые классы java.time поддерживают наносекундное разрешение. Эта поддержка включает в себя анализ и генерацию девяти цифр доли секунды. Например, когда вы используете API-интерфейс DateTimeFormatter java.time.format, буква S шаблона обозначает "долю секунды", а не "миллисекунды", и может справляться со значениями наносекунд.

Instant

Например, класс Instant представляет момент в UTC. Его метод toString генерирует объект String используя стандартный формат ISO 8601. Буква Z на конце означает UTC, произносится "Зулу".

instant.toString()  // Generate a 'String' representing this moment, using standard ISO 8601 format.

2013-08-20T12: 34: 56.123456789Z

Обратите внимание, что захват текущего момента в Java 8 ограничен разрешением в миллисекундах. Классы java.time могут содержать значение в наносекундах, но могут определять текущее время только в миллисекундах. Это ограничение связано с реализацией Clock. В Java 9 и более поздних версиях новая реализация Clock может захватить текущий момент в более высоком разрешении, в зависимости от ограничений вашего хост-оборудования и операционной системы, обычно, по моему опыту, микросекунды.

Instant instant = Instant.now() ;  // Capture the current moment. May be in milliseconds or microseconds rather than the maximum resolution of nanoseconds.

LocalDateTime

В вашем примере строки ввода 2015-05-09 00:10:23.999750900 отсутствует индикатор часового пояса или смещения от UTC. Это означает, что он не представляет момент, не является точкой на временной шкале. Вместо этого он представляет потенциальные моменты в диапазоне около 26-27 часов, в диапазоне часовых поясов по всему миру.

Сравнивает такой ввод как объект LocalDateTime. Во-первых, замените ПРОБЕЛ в середине буквой T чтобы соответствовать формату ISO 8601, который используется по умолчанию при разборе/генерации строк. Поэтому нет необходимости указывать шаблон форматирования.

LocalDateTime ldt = 
        LocalDateTime.parse( 
            "2015-05-09 00:10:23.999750900".replace( " " , "T" )  // Replace SPACE in middle with 'T' to comply with ISO 8601 standard format.
        ) 
;

java.sql.Timestamp

Класс java.sql.Timestamp также обрабатывает наносекундное разрешение, но неуклюже. Обычно лучше всего выполнять свою работу в классах java.time. Больше нет необходимости использовать Timestamp снова, Timestamp с JDBC 4.2 и выше.

myPreparedStatement.setObject( … , instant ) ;

И поиск.

Instant instant = myResultSet.getObject( … , Instant.class ) ;

OffsetDateTime

Поддержка Instant не обязательна в спецификации JDBC, но есть OffsetDateTime. Поэтому, если вышеприведенный код не работает с вашим драйвером JDBC, используйте следующее.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 
myPreparedStatement.setObject( … , odt ) ;

И поиск.

Instant instant = myResultSet.getObject( … , OffsetDateTime.class ).toInstant() ;

При использовании драйвера старше до 4.2 JDBC, вы можете использовать toInstant и from методов идти вперед и назад между java.sql.Timestamp и java.time. Эти новые методы преобразования были добавлены в старые унаследованные классы.

Table of date-time types in Java (both legacy and modern) and in standard SQL


О 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 и другие.