PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Кой е най-препоръчителният начин за съхраняване на време в PostgreSQL с помощта на Java?

Всяка стратегия за съхранение на данни за дата и час в PostgreSQL трябва, IMO, да разчита на тези две точки:

  • Вашето решение не трябва никога зависи от настройката на часовата зона на сървъра или клиента.
  • Понастоящем PostgreSQL (както повечето бази данни) няма тип данни за съхраняване на пълен дата и час с часова зона. Така че трябва да изберете между Instant или LocalDateTime тип данни.

Моята рецепта следва.

Ако искате да запишете физическиямомента когато се е случило конкретно събитие (истинска „timestamp ", обикновено някакво събитие за създаване/модификация/изтриване), след което използвайте:

  • Java:Instant (Java 8 или Jodatime).
  • JDBC:java.sql.Timestamp
  • PostgreSQL:TIMESTAMP WITH TIMEZONE (TIMESTAMPTZ )

(Не позволявайте на PostgreSQL специфични типове данни WITH TIMEZONE /WITHOUT TIMEZONE обърка ви:нито един от тях всъщност не съхранява часова зона)

Някакъв шаблонен код:следното предполага, че ps е PreparedStatement , rs a ResultSet и tzUTC е статичен Calendar обект, съответстващ на UTC часова зона.

public static final Calendar tzUTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));  

Напишете Instant към база данни TIMESTAMPTZ :

Instant instant = ...;
Timestamp ts = instant != null ? Timestamp.from(instant) : null;
ps.setTimestamp(col, ts, tzUTC);   // column is TIMESTAMPTZ!

Прочетете Instant от база данни TIMESTAMPTZ :

Timestamp ts = rs.getTimestamp(col,tzUTC); // column is TIMESTAMPTZ
Instant inst = ts !=null ? ts.toInstant() : null;

Това работи безопасно, ако вашият тип PG е TIMESTAMPTZ (В този случай calendarUTC няма ефект в този код; но винаги е препоръчително да не зависи от часовите зони по подразбиране). „Безопасно“ означава, че резултатът няма да зависи от часовата зона на сървъра или базата данни , или информация за часовите зони:операцията е напълно обратима и каквото и да се случи с настройките на часовите зони, винаги ще получавате същия „момент за време“, който първоначално сте имали от страна на Java.

Ако вместо времева марка (момент на физическата времева линия) имате работа с „гражданска“ местна дата-час (тоест набор от полета {year-month-day hour:min:sec(:msecs)} ), бихте използвали:

  • Java:LocalDateTime (Java 8 или Jodatime).
  • JDBC:java.sql.Timestamp
  • PostgreSQL:TIMESTAMP WITHOUT TIMEZONE (TIMESTAMP )

Прочетете LocalDateTime от база данни TIMESTAMP :

Timestamp ts = rs.getTimestamp(col, tzUTC); //
LocalDateTime localDt = null;
if( ts != null ) 
    localDt =  LocalDateTime.ofInstant(Instant.ofEpochMilli(ts.getTime()), ZoneOffset.UTC);

Напишете LocalDateTime към база данни TIMESTAMP :

  Timestamp ts = null;
  if( localDt != null)    
      ts = new Timestamp(localDt.toInstant(ZoneOffset.UTC).toEpochMilli()), tzUTC);
  ps.setTimestamp(colNum,ts, tzUTC); 

Отново, тази стратегия е безопасна и можете да спите спокойно:ако сте съхранили 2011-10-30 23:59:30 , вие ще извличате тези точни полета (час=23, минути=59... и т.н.) винаги, без значение какво - дори ако утре часовата зона на вашия Postgresql сървър (или клиент) се промени, или вашата JVM или часовата зона на вашата ОС, или ако държавата ви промени правилата си за DST и т.н.

Добавено:Ако искате (изглежда естествено изискване) да съхранявате пълната спецификация за дата и час (ZonedDatetime :времевата марка заедно с часовата зона, която имплицитно включва и пълната гражданска информация за дата и час - плюс часовата зона)... тогава имам лоши новини за вас:PostgreSQL няма тип данни за това (нито други бази данни, доколкото ми е известно) . Трябва да създадете свое собствено хранилище, може би в двойка полета:може да са двата по-горе типа (силно излишни, макар и ефективни за извличане и изчисляване), или един от тях плюс отместването на времето (губите информацията за часовата зона, някои изчисления стават трудни, а някои невъзможни), или един от тях плюс часовата зона (като низ; някои изчисления могат да бъдат изключително скъпи).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вземете броя на записите, засегнати от INSERT или UPDATE в PostgreSQL

  2. Как да сведете до минимум RPO за вашите PostgreSQL бази данни, използвайки възстановяване на точка във времето

  3. деактивирайте БЕЛЕЖИТЕ в изхода на psql

  4. Добавяне на външен ключ към релсов модел

  5. Инсталацията на Odoo на Mac не можа да изпълни команда LESSC