2

I just discovered, that storing dates in utc is not ideally correct if we are also dealing with dates in the future. It seems to be the case because, timezones seem to change more often than we think they do. Fortunately, we seem to have the IANA tzdb that seems to get updated periodically, but, confusingly, postgres seems to use a specific version of the db which it seems to have at build time..

So, my question is, if the timezones are changing, with daylight saving going on, with political, geographical adjustments happening, and our database is not with the latest of the tzdb, how would we be able to keep track of the accuracy of the dates in the system? Additionally, would libraries like date-fns-tz basically not be accurate to account for new timezone changes?

Ideally I would think a library would make a network call to a central server that would maintain the latest changes, but, it doesn't seem to be the case. How are the latest date/timezone changes usually dealt with?

juztcode
  • 1,196
  • 2
  • 21
  • 46
  • 1
    The times are always correct *precisely* because they use the unchanging timezone *names* instead of a changing offset. No matter how DST rules change, shops in Athens Greece always open at 10 AM Europe/Athens in normal days, whether Winter or Summer time is used, and will keep doing so even if DST is abandoned. The IANA tzdb includes historical rules so should the DST rules be abandoned, older summer time *offsets* will remain `+3:00`, before the rule change. – Panagiotis Kanavos Dec 10 '22 at 15:40
  • 1
    1) The time zone data is updated at minor releases which happen ~every 3 months [Versioning](https://www.postgresql.org/support/versioning/). From the last release: *This release also updates time zone data files to use tzdata release 2022f.*. 2) If you are building Postgres yourself you can point at system timezone db [Install](https://www.postgresql.org/docs/current/install-procedure.html): *--with-system-tzdata=DIRECTORY* 3) You can play with [Date/Time conf](https://www.postgresql.org/docs/current/datetime-config-files.html) files. – Adrian Klaver Dec 10 '22 at 16:07
  • 1
    The timezone data isn't set in stone. When there are sudden changes, all products/vendors issue patches. When Egypt changed DST rules in short notice, a new TZDB version was made, Windows got an Update to fix this, JodaTime, NodaTime etc released new versions. – Panagiotis Kanavos Dec 10 '22 at 16:17
  • 4) Store your timestamps in field of type `timestamptz`. This will rotate the value to UTC on storage and future proof it. – Adrian Klaver Dec 10 '22 at 16:19
  • @PanagiotisKanavos , libraries may release new versions, but, that would require developers to be aware of the changes and update libs – juztcode Dec 10 '22 at 16:23
  • @AdrianKlaver , my concern is if a running version of postgres, does this maintainence itself? Or are the changes reflected in a patch that requires manual update? – juztcode Dec 10 '22 at 16:24
  • @juztcode which is why we use timezones instead of offsets. So there are fewer things to keep up to date. As for being aware of changes - you don't stay long in business if you miss such things. Having to handle multiple timezones usually means international trade/travels, which by extension mean errors are far more costly. – Panagiotis Kanavos Dec 10 '22 at 16:28
  • 1
    Assuming you are using some sort of package manager you would need to do the package upgrade process. If you are building from source you would need to redo the build and compile. In either case you would want to keep up with minor upgrades for the bug and security fixes alone. – Adrian Klaver Dec 10 '22 at 16:34
  • @PanagiotisKanavos , could you explain how a timezone would encode data different from an offset ? EST would be (UTC-5), I'm calling this -5 an offset. But, with DST, it would be (UTC-4) , but, the actual input of whether the DST is on or not, is something that has to be maintained, which is where the question of the updated tzdb comees in play – juztcode Dec 10 '22 at 16:35
  • An offset is a fixed time differential, a timezone is a set of rules that change that offset for a given point in time. So a timezone may have a different offset for a timestamp in a year, in the past and in the future(assuming the new rules are published before the actaul change). – Adrian Klaver Dec 10 '22 at 16:40
  • @AdrianKlaver , but, what kind of rule would it have other than an offset from the standard UTC? – juztcode Dec 10 '22 at 16:46
  • The point is that the rule adapts the timestamp to its place in the time continuum. For example see [tz database](https://en.wikipedia.org/wiki/Tz_database) in particular [Rule example](https://en.wikipedia.org/wiki/Tz_database#Example_zone_and_rule_lines). An offset is just that an offset from UTC and that may represent multiple timezones e.g `-5` can be `EST` or `ACT`. – Adrian Klaver Dec 10 '22 at 17:39
  • an offset would not represent a timezone uniquely, but, in calculative terms, just to represent a date/time in one zone to another, what purposes would a timezone add additionally? – juztcode Dec 10 '22 at 17:51
  • Identify where the value came from. It might be relevant that a value was coming from the US East coast vs Brazil ACT. – Adrian Klaver Dec 10 '22 at 23:02
  • @AdrianKlaver , `The time zone data is updated at minor releases which happen ~every 3 months Versioning. From the last release: This release also updates time zone data files to use tzdata release 2022f.` , would this also mean we gotta upgrade postgres patches manually? – juztcode Dec 11 '22 at 04:49
  • As I said before you just use the package manager to upgrade the package. – Adrian Klaver Dec 11 '22 at 05:15

3 Answers3

4

The IANA time zone database collects the global knowledge about what time zone was in effect at what time in every part of the world. That information is naturally incomplete, specifically when it comes to the future. A (IANA) time zone is not an offset from UTC, but a rule that says when which offset from UTC is active. EST is not a time zone in that sense, it is an abbreviation for a certain UTC offset. If you live in New York, you will sometimes have EST, sometimes EDT, depending on the rules for the time zone America/New_York. Of course you should update the time zone database, but not because the timestamps change (they are immutable), but because the way that the timestamps are displayed in a certain time zone can change.

What is stored in the database is always an UTC timestamp, so the timestamp itself is immutable. What changes is the representation. So if you predict that the world will end next July 15 at noon Austrian time, and the Austrian government abolishes daylight savings time, your prediction will be an hour off (unless you expect the cataclysm to follow Austrian legislation). If you are worried about that, make your predictions in UTC or at least add the UTC offset to the timestamp.

If you store the timestamp with time zone in the database, and you query it today with timezone set to Europe/Vienna, you will get a certain result. If you update the time zone database, and the new legislation is reflected in the update, then the same query will return a different result tomorrow. However, it will still be the same timestamp, only the UTC offset in use will be different:

SELECT TIMESTAMP WITH TIME ZONE '2023-07-15 12:00:00+02'
     = TIMESTAMP WITH TIME ZONE '2023-07-15 11:00:00+01';

 ?column? 
══════════
 t
(1 row)
Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • 1
    Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/250340/discussion-on-answer-by-laurenz-albe-dealing-with-utc-dates-and-the-future). – sideshowbarker Dec 12 '22 at 05:53
1

To clarify @Laurenz's statement in the comments further with an example, lets take an extreme case of samoa , where they switched from GMT-11 timezone, to GMT+13 skipping an entire day.

While ignoring what a timezone actually is (different similar opinions in the comments), for the purpose of the calculations below, lets just consider it a value offset from the standard UTC. Also, do note, I use my own symbolic ways to calculate, but, it is very understandable, hopefully ;-)

so, samoa on Dec 29, 2011 skipped a day, how? Based on what I found, when the clock struck midnight they effectively skipped Friday. But, the unix timestamp remains equivalent/unchanged:

   GMT-11
(-)GMT+13
__________
 = 24hrs
 
Let, WST=GMT-11

    2011-12-29 T 24:00:00 - 11 (clock strikes midnight)
  = 2011-12-30 T 00:00:00 - 11 (WST)
  = 2011-12-30 T 11:00:00      (UTC)  
  
now the switch occurs, WST=GMT+13
   2011-12-31 T 00:00:00  + 13 (WST)
 = 2011-12-31 T-13:00:00       (UTC)
 = 2011-12-30 T 11:00:00       (UTC)

So, as far as I can see, storing future dates does not really affect the value of the date itself. But, what it does affect is the way the dates are displayed, e.g. if the timezone info was not updated, people would still see the day after the 29th at samoa as Friday, 30th. But, in that case, it would be Fri, 30th GMT-11, whereas if the information was updated, it would be Sat, 31, GMT+13. So, all is well.

more details in the comment section of @Laurenz's answer

Also, as @Adrian mentions above, softwares that deal with timezones, come packaged with a version of tzdb if they support the conversion at all. It seems to be the case in postgres as well though it seem you can configure it to use the system's version. For such cases, you gotta update the software or the system's db itself.

juztcode
  • 1,196
  • 2
  • 21
  • 46
0

I understand that you want to store a future point in time, like "10:00am on July 5th 2078 in the time zone of Australia/Sydney", regardless of what offset that time zone has compared to UTC when you retrieve the point in time again. And when the time comes, the point in time might not even exist, because it is being skipped for the introduction of daylight saving time (or it might exist more than once).

Speaking XML Schema, the information you want to store consists of

  • a dateTime without timezoneOffset, in the given example 2078-07-05T10:00:00 (no trailing Z)
  • plus a time zone, given as a string from the IANA database, in the given example Australia/Sydney.

I don't know how this is best stored in a PostgreSQL database, whether as two separate strings, or in a special data type. The PostgreSQL documentation says:

All timezone-aware dates and times are stored internally in UTC. They are converted to local time in the zone specified by the TimeZone configuration parameter before being displayed to the client.

That sounds to me as if the UTC value was fixed, and the local time value in a given time zone might change if daylight saving time is introduced or abolished in that time zone. (Am I correct here?) You want it the other way round: The local time remains the same and the UTC value might change after DST introduction/abolition.

For example, assume that polling stations for the next general election open at 2025-09-21T08:00:00+02:00 in my time zone. But if my country abolishes DST before then, they will open instead on 2025-09-21T08:00:00+01:00 without an explicit rescheduling. In other words: The UTC time changes, but the local time does not.

Or consider a flight whose local departure time and time zone are stored, which has a duration of 10 hours and arrives in another time zone. Its local arrival time then changes when the offset of the departure time zone changes, for example, because daylight saving time is introduced or abolished in that country on day X, but the offset of the arrival time zone does not change. An app that computes the local arrival time must then show a changed arrival time when it is executed on day X or later, although the stored data (the local departure time, departure time zone, arrival time zone and flight duration) have not changed. The required change can happen automatically if the app uses a library that is based on the IANA time zone database and receives an upgrade that includes the DST introduction/abolition before day X arrives.

For an example of such a library, see https://day.js.org/docs/en/timezone/parsing-in-zone.

Heiko Theißen
  • 12,807
  • 2
  • 7
  • 31
  • 1
    The basic premise is completely wrong - that using a timezone fixes the offset when it's the exact oppostie. The Javascript function claims to format but does no formatting at all. Nor does it have anything to do with the question itself - how *PostgreSQL* datetimes with timezones are handled – Panagiotis Kanavos Dec 10 '22 at 15:47
  • 1
    Then the answer is simply wrong and the function actively harmful because it loses the timezone information – Panagiotis Kanavos Dec 10 '22 at 15:51
  • 1
    You don't need to do that in the first place. Timezones are better, *especially* for future time. No matter how rules change, 7 AM Europe/Oslo refers to the same local time. If a library or language can't handle that, libraries like JodaTime or NodaTime are created to fix this – Panagiotis Kanavos Dec 10 '22 at 16:04