sql >> Database teknologi >  >> RDS >> PostgreSQL

Repræsenterer en fremtidig tid i PostgreSQL

Det lyder som om du vil gemme en lokaltid med hensyn til en bestemt tidszone. I så fald skal du gemme et timestamp (uden tidszone) og timezone i en separat kolonne.

Antag for eksempel, at du vil optage en begivenhed, der finder sted kl. 10.00 den 26. februar 2030 i Chicago, og det skal være kl. 10.00 lokal tid uanset den tidszoneregel, der er gældende på den dato.

Hvis databasen gemmer tidsstemplet uden tidszone:

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 |
+---------------------+-----------------+

Så senere kan du finde UTC-dato-klokkeslættet for begivenheden ved hjælp af

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 |
+---------------------+

Forespørgslen returnerer UTC datetime, 2030-02-26 16:00:00 , hvilket svarer til 2030-02-26 10:00:00 lokaltid i Chicago.

Bruger AT TIME ZONE forsinker anvendelsen af ​​tidszonereglerne til hvornår forespørgslen er lavet i stedet for når timestamptz blev indsat.

Bruger AT TIME ZONE på et timestamp lokaliserer dato og klokkeslæt til den givne tidszone, men rapporterer dato og klokkeslæt i brugerens tidszone .Brug af AT TIME ZONE på en timestamptz konverterer dato og klokkeslæt til den givne tidszone og dropper derefter forskydningen og returnerer således et timestamp .Over, AT TIME ZONE bruges to gange:først for at lokalisere et timestamp og derefter konvertere den returnerede timestamptz til en ny tidszone (UTC). Resultatet er et timestamp i UTC.

Her er et eksempel, der demonstrerer AT TIME ZONE s adfærd på 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 og 2030-02-26 08:00:00-08 er de samme dato og klokkeslæt, men rapporteret i forskellige brugertidszoner. Dette viser kl. 10.00 i Chicago er kl. 8.00 i Los Angeles (ved at bruge de nuværende tidszonedefinitioner):

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

Et alternativ til at bruge AT TIME ZONE to gange er at indstille brugerens tidszone til UTC . Så kunne du bruge

select localtime AT TIME ZONE tzone

Bemærk, at når det gøres på denne måde, en timestamptz returneres i stedet for et timestamp .

Vær opmærksom på, at lagring af lokale tider kan være problematisk, fordi der kan være ikke-eksisterende tidspunkter og tvetydige tidspunkter. For eksempel 2018-03-11 02:30:00 er en ikke-eksisterende lokaltid i America/Chicago . Postgresql normaliserer ikke-eksisterende lokale tider ved at antage, at det refererer til den tilsvarende tid efter sommertid (DST) er begyndt (som om nogen glemte at stille deres ur frem):

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)

Et eksempel på en tvetydig lokaltid er 2018-11-04 01:00:00 i America/Chicago . Det sker to gange på grund af sommertid. Postgresql løser denne tvetydighed ved at vælge det senere tidspunkt, efter sommertid er afsluttet:

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 |
+---------------------+

Bemærk, at det betyder, at der ikke er nogen måde at henvise til 2018-11-04 06:00:00 UTC ved at gemme lokale tider i America/Chicago tidszone:

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. Sådan knytter du en MySQL JSON-kolonne til en Java-entitetsejendom ved hjælp af JPA og Hibernate

  2. Find dublerede rækker i databasen

  3. INDSÆT slettede værdier i en tabel før DELETE med en DELETE TRIGGER

  4. Transaktionsstyring med DAO'er