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

Представяне на бъдещо време в PostgreSQL

Изглежда, че искате да съхраните местно време по отношение на определена часова зона. В този случай запазете timestamp (без часова зона) и timezone в отделна колона.

Да предположим например, че искате да запишете събитие, което ще се случи в 10 сутринта на 26 февруари 2030 г. в Чикаго и трябва да е в 10 сутринта местно време независимо от правилото за часовата зона в сила на тази дата.

Ако базата данни съхранява клеймото за време без часова зона:

unutbu=# select '2030-02-26 10:00:00'::timestamp as localtime, 'America/Chicago' AS tzone;
+---------------------+-----------------+
|      localtime      |      tzone      |
+---------------------+-----------------+
| 2030-02-26 10:00:00 | America/Chicago |
+---------------------+-----------------+

След това по-късно можете да намерите UTC датата и часа на събитието, като използвате

unutbu=# select '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 16:00:00 |
+---------------------+

Заявката връща UTC дата и час, 2030-02-26 16:00:00 , което съответства на 2030-02-26 10:00:00 местно време в Чикаго.

Използване на AT TIME ZONE забавя прилагането на правилата за часовата зона до кога е направена заявката вместо кога timestamptz беше вмъкнато.

Използване на AT TIME ZONE на timestamp локализира датата и часа към дадената часова зона, но отчита датата и часът в часовата зона на потребителя .Използване на AT TIME ZONE на timestamptz преобразува datetime в дадената часова зона, след което премахва отместването, като по този начин връща timestamp .По-горе, AT TIME ZONE се използва два пъти:първо за локализиране на timestamp и следващ за преобразуване на върнатия timestamptz към нова часова зона (UTC). Резултатът е timestamp в UTC.

Ето пример, демонстриращ AT TIME ZONE поведението на timestamp s:

unutbu=# SET timezone = 'America/Chicago';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 10:00:00-06 |
+------------------------+

unutbu=# SET timezone = 'America/Los_Angeles';
unutbu=# SELECT '2030-02-26 10:00:00'::timestamp AT TIME ZONE 'America/Chicago';
+------------------------+
|        timezone        |
+------------------------+
| 2030-02-26 08:00:00-08 |
+------------------------+

2030-02-26 10:00:00-06 и 2030-02-26 08:00:00-08 са едни и същи дати и часове, но са отчетени в различни потребителски часови зони. Това показва, че 10 сутринта в Чикаго е 8 сутринта в Лос Анджелис (използвайки текущите дефиниции на часовата зона):

unutbu=# SELECT '2030-02-26 10:00:00-06'::timestamptz AT TIME ZONE 'America/Los_Angeles';
+---------------------+
|      timezone       |
+---------------------+
| 2030-02-26 08:00:00 |
+---------------------+

Алтернатива на използването на AT TIME ZONE два пъти е задаване на потребителската часова зона до UTC . След това можете да използвате

select localtime AT TIME ZONE tzone

Имайте предвид, че когато се прави по този начин, timestamptz се връща вместо timestamp .

Имайте предвид, че съхраняването на местни часове може да бъде проблематично, тъй като може да има несъществуващи часове и двусмислени времена. Например 2018-03-11 02:30:00 е несъществуващо местно време в America/Chicago . Postgresql нормализира несъществуващи местни времена, като приема, че се отнася за съответния час след началото на лятното часово време (DST) (сякаш някой е забравил да настрои часовника си напред):

unutbu=# select '2018-03-11 02:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

unutbu=# select '2018-03-11 03:30:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-03-11 08:30:00 |
+---------------------+
(1 row)

Пример за двусмислено местно време е 2018-11-04 01:00:00 в America/Chicago . Среща се два пъти поради лятното часово време. Postgresql разрешава тази неяснота, като избира по-късния час, след края на лятното часово време:

unutbu=# select '2018-11-04 01:00:00'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 07:00:00 |
+---------------------+

Обърнете внимание, че това означава, че няма начин да се препрати към 2018-11-04 06:00:00 UTC чрез съхраняване на местно време в America/Chicago часова зона:

unutbu=# select '2018-11-04 00:59:59'::timestamp AT TIME ZONE 'America/Chicago' AT TIME ZONE 'UTC';
+---------------------+
|      timezone       |
+---------------------+
| 2018-11-04 05:59:59 |
+---------------------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP\HTML скрипт за автоматично попълване на полетата на формуляра, когато даден елемент е избран от падащ списък

  2. Как да се справя с отварянето/затварянето на Db връзка в Go приложение?

  3. Postgres връзката е затворена грешка в Spring Boot

  4. Как age() работи в PostgreSQL

  5. Как да извикам функция на база данни с помощта на SQLAlchemy във Flask?