ТЛ; др
Как мы храним объекты postgres datetime в классах java pojo для объектов json?
Это зависит.
Что касается JSON, для значений даты и времени нет типов данных JSON. Генерация строк в стандартном формате ISO 8601.
Я пытаюсь отсортировать их
Классы java.time знают, как сортировать себя, реализуя интерфейс Comparable
.
если я должен сравнивать дату и время?
Всегда используйте умные объекты, а не тупые строки. Вот почему у вас есть JDBC технология и JDBC драйверы .
Сравнение дат не работает
Никогда не используйте класс java.util.Date
. Никогда не используйте java.sql.Date
класс. Используйте только java.time классы.
Сравнение строк. Отлично работает для объектов datetime
Неа. Строки даты и времени могут быть представлены во всех видах форматов, с использованием всех видов человеческих языков и культурных норм, с применением различных часовых поясов или смещений от UTC. Строки не подходят для сортировки значений даты и времени. Используйте умные java.time объекты, а не тупые строки.
Или выполните сортировку на стороне базы данных, где Postgres оптимизирован для такой работы.
приватное поле даты А; личное поле DateB;
Сделать так:
private Instant fieldA, fieldB ;
…
boolean isAEarlier = fieldA.isBefore( fieldB ) ;
boolean isAtheSame = fieldA.equals( fieldB ) ; // Note that some other java.time classes have `isEqual` method as well as `equals` method.
boolean isALater = fieldA.isAfter( fieldB ) ;
boolean isAEqualToOrLaterThan = ( ! fieldA.isBefore( fieldB ) ) ; // "Is equal to or later than" is a common use-case. "Not before" is a logical shortcut with the same effect.
java.time
Класс Date
теперь является устаревшим, частью ужасно хлопотных старых классов даты и времени, которые были вытеснены классами java.time несколько лет назад. Никогда не используйте Date
, Calendar
, SimpleDateFormat
и т. П.
Ваш вопрос является дубликатом многих других, поэтому я буду кратким здесь. Поиск переполнения стека, чтобы узнать больше.
Прилагается к временной шкале
Для столбца базы данных типа TIMESTAMP WITH TIME ZONE
, определенного в стандарте SQL и используемого в Postgres, который представляет момент, конкретную точку на временной шкале.
В Postgres , этот тип имеет разрешение микросекунд и равен всегда в UTC . Любые входы с индикатором часового пояса или смещения от UTC настраиваются на UTC, а зона / смещение затем отбрасываются. Таким образом, тип немного неправильный, так как исходная зона / смещение забыта, а сохраненное значение всегда в UTC. Другие базы данных могут отличаться в этом поведении, поэтому будьте осторожны, поскольку спецификация SQL едва затрагивает тему даты и времени.
Помните, что при использовании инструментов, отличных от JDBC , ваш инструмент может вводить часовой пояс или offset-from-UTC после получения сохраненного значения UTC ; Это может вводить в заблуждение и вводить в заблуждение новичка (и, на мой взгляд, это неудачное дизайнерское решение).
В Java, как правило, лучше всего работать в UTC . Будучи программистом, учитесь думать, хранить и обмениваться моментами в формате UTC. Обычно для этого используйте класс Instant
. Для определения переменных-членов в ваших классах, Instant
- ваш переходящий класс.
Instant instant = Instant.now() ; // Capture the current moment in UTC, with a resolution as fine as nanoseconds.
Возможно, вы захотите урезать любые наносекунды до микросекунд, чтобы соответствовать полученным значениям из Postgres. Укажите разрешение с помощью ChronoUnit
.
Instant instant = Instant.now().truncatedTo( ChronoUnit.MICROS ) ;
Для представления пользователю в его желаемом / ожидаемом часовом поясе назначьте ZonedId
, чтобы получить ZonedDateTime
.
Укажите собственное имя часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 3-4-буквенное сокращение, такое как EST
или IST
, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Чтобы вернуться в UTC, извлеките Instant
.
Instant instant = zdt.toInstant() ;
Чтобы сгенерировать локализованный текст, представляющий значение объекта ZonedDateTime
, используйте DateTimeFormatter
. Поиск переполнения стека для получения дополнительной информации.
Не привязан к временной шкале
Тип базы данных TIMESTAMP WITHOUT TIME ZONE
преднамеренно лишен какой-либо концепции часового пояса или смещения от UTC. Таким образом, он не представляет момент, является не точкой на временной шкале и является не тем, что вы, вероятно, хотите в бизнес-приложении, за исключением случаев, когда:
- Планирование встреч на будущее.
- Представление понятия даты и времени для каждой зоны или любой зоны, а не конкретной зоны.
В Postgres любая зона или смещение, сопровождающие ввод, игнорируются. Дата и время суток сохраняются без изменений.
Соответствующий тип в Java: LocalDateTime
.
«Локальный» в этом имени класса не означает «конкретный населенный пункт». Как раз наоборот! Это означает каждый населенный пункт или любой населенный пункт, но не конкретный населенный пункт. Если вы этого не понимаете, изучите, прочитайте документацию по классу и выполните поиск переполнения стека.
База данных
Используйте умные объекты, а не тупые строки для обмена значениями даты и времени с вашей базой данных.
Начиная с JDBC 4.2 , вы можете напрямую обмениваться java.time объектами с базой данных. Никогда не используйте java.sql.Timestamp
, java.sql.Date
и java.sql.Time
.
Хранение.
myPreparedStatement.setObject( … , instant ) ;
индексирование.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
JSON
Спецификация JSON определяет очень мало типов данных, и ни один из них не связан с датой и временем. Вы сами по себе там. То же самое для XML .
ISO 8601
При сериализации значений даты и времени в виде текста используйте стандартные форматы ISO 8601 . Они разработаны, чтобы быть практичными и полезными, и чтобы избежать двусмысленности. Они разработаны так, чтобы их можно было легко анализировать с помощью машин, а также легко читать людям в разных культурах.
Классы java.time по умолчанию используют эти стандартные форматы при разборе / создании строк даты и времени. Просто позвоните parse
и toString
в различные классы.
Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;
String output = instant.toString() ;
На данный момент формат ISO 8601 похож на обычный формат SQL, за исключением того, что в SQL используется ПРОБЕЛ в середине, а не T
. Этот факт в значительной степени не имеет значения, поскольку вы должны использовать объекты, а не строки между Java и вашей базой данных, как упоминалось выше.
Half-Open
В связи с темой сравнения… При работе с отрезками времени научитесь последовательно использовать подход Half-Open, где начало включительно , а окончание исключительно . Поиск переполнения стека, чтобы узнать больше.
О 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 .