74

There is a long and quite elucidating answer on the differences between

  • TIMESTAMP WITH TIME ZONE -vs-
  • TIMESTAMP WITHOUT TIME ZONE

available in the SO post Ignoring time zones altogether in Rails and PostgreSQL.

What I would like to know is: Are there any valid use cases for actually using TIMESTAMP WITHOUT TIME ZONE or should it be considered an anti-pattern?

2
  • 1
    This question runs the risk of being closed being "primarily opinion based". I've tried to give some objective views in my answer below. Commented Feb 16, 2014 at 15:24
  • 5
    This issue is quite real, each data type having a very different meaning. So I would certainly not consider this Question as primarily opinion based. Commented Dec 13, 2016 at 8:27

7 Answers 7

56

This is stated in a lot of places, but I think it worth mentioning always when we compare the timestamp with time zone with timestamp without time zone types: the timestamp WITH time zone does not store the time zone information along with the timestamp. What it does is to store every data in UTC time zone, as stated in the docs:

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

It is considered valid for some to use timestamp WITHOUT time zone in situations where (1) everything is in the same timezone or (2) the application layer handles the time zone and just store everything in a certain time zone (usually UTC). But it is also considered an anti-pattern, simple because the correct solution for (1) is to configure the TimeZone setting to the given one timezone for the system and (2) is already solved, as PostgreSQL already stores everything on the same timezone (UTC).

Now, with those two down, I can came with only one good reason to use timestamp WITHOUT time zone. That is when you want to store events in the future and that some kind of alert must be triggered when we got to that time. That could be good for timestamp WITH time zone if, and only if, the rules defined by region's laws about time zone didn't ever change. The most common rule that changes is about the adoption or not of day light saving time (DST).

For example, imagine that you are at, let's say, 2013-06-15 (not yet in DST) schedule some event to happen at 2013-01-15 10:00 (which would be already in DST), and at 2013-06-15 your region was designated to adopt DST; but, some time after that, the government changed the rule and say your region will no longer use DST, and suddenly your scheduled time becomes 2013-01-15 11:00 (instead of 10:00), that if you use timestamp WITH time zone, and keep your TZ configurations up-to-date. Of course you may also notice that it is possible to treat such cases also with time zone, if you keep track of the rule changes in the regions/timezones of your interest, and update the affected records.

Worth mentioning that some regions does often change these rules (like at Brazil, some states - not the entire country - often change), but in most cases it changes it very earlier, so your users would be affected only by events scheduled very far from the current time.

With all that said, I only have one more suggestion. If you do have users, logs, or anything on different timezones, store the timezone they are coming from somewhere and choose and use timestamp with time zone. That way you can (1) cross events happening closer to each other for different sources (independent of their timezones) and (2) show the original time (the clock time) the event has happened.

1
38

Yes. There are use-cases for TIMESTAMP WITHOUT TIME ZONE.

  • In common business apps this type would only be used for:
    • Booking future appointments
    • Representing the same time-of-day across various time zones, such as noon on the 23rd in Tokyo and in Paris (two different moments hours apart, same time-of-day)
  • For tracking moments, specific points on the timeline, always use TIMESTAMP WITH TIME ZONE, not WITHOUT.

TIMESTAMP WITHOUT TIME ZONE values are not a point on the timeline, not actual moments. They represent a rough idea about potential moments, possible points on the timeline along a range of about 26-27 hours (the range of time zones around the globe). They have no real meaning until you apply a time zone or offset-from-UTC.

Ex: Christmas

For example, say you need to record the start of holidays/holy days.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

To record the fact that Christmas starts after midnight on December 25 this year, we need to say 2016-12-25 00:00:00 without any time zone. Early in Santa’s day he visits Auckland NZ just after midnight, as that is one of the earliest midnights on the globe. Then he works his way westward, as the next midnight happens, soon reaching the Philippines. Then the reindeer move on in a westerly direction, reaching India at its midnight which happens to occur several hours after that Auckland midnight. Much later still is midnight in Paris FR, and still later midnight in Montreal CA. All these visits by Santa happen at different moments is time, yet all happened shortly after midnight, per each locality’s own midnight.

So recording 2016-12-25 00:00:00 without any time zone as the beginning of Christmas is informative and legitimate, but only vaguely. Until you say “Christmas in Auckland” or “Christmas in Montréal”, we do not have a specific moment in time. If you are recording the actual moment each time the sleigh touched down, you would use TIMESTAMP WITH TIME ZONE rather than the WITHOUT type.

Similar to Christmas is New Year’s Eve. When the Times Square Ball drops in New York, people in Seattle are still chilling their champagne and preparing their party horns. Yet we would record the idea of the New Year moment as 2017-01-01 00:00:00 in a TIMESTAMP WITHOUT TIME ZONE. In contrast, if we want to record when the ball dropped in New York, or when the people in Seattle blew their horns, we would instead use TIMESTAMP WITH TIME ZONE (not WITHOUT) to record those actual moments, each three hours apart from the other.

Ex: Factory Shifts

Another example might be recording a policy that involves wall-clock time across various locations. Say we have factories in Detroit, Düsseldorf, and Delhi. If we say that at all three factories the first shift begins at 6 AM with a lunch break at 11:30 AM, that could be recorded as a TIMESTAMP WITHOUT TIME ZONE. Again, this information is useful in a vague way but does not indicate a specific moment in time until we apply a time zone. A new day dawns earlier in the east. So the Delhi factory will be the first to open at its 6 AM. Hours later, the Düsseldorf factory begins work at its 6 AM. But the Detroit factory won't actually open until another six hours later, when its 6 AM happens.

Contrast this idea (of when the factory shift generally begins) to the historical fact of when did each factory worker clock-in to begin their shift on a particular day. The clock-in is a real moment, an actual point on the timeline. So we would record that in a column of type TIMESTAMP WITH TIME ZONE rather than the WITHOUT type.

So, yes, there are legitimate use-cases for TIMESTAMP WITHOUT TIME ZONE. But in my experience with business apps, they are relatively rare. In business, we tend to care about actual moments: when did the invoice actually arrive, when exactly does that contract go into effect, at what moment did that bank transaction execute. So in such common situations, we want the TIMESTAMP WITH TIME ZONE type.

For more discussion, see my Answer to the similar Question, Should I store UTC timestamps or localtime for shifts

Postgres

Note that Postgres specifically never saves the time zone information specified when inserting a timestamp.

  • TIMESTAMP WITH TIME ZONE
    • Any specified time zone or offset included with the input data is used to adjust the value to UTC and stored. The passed zone/offset info is then discarded. Think of TIMESTAMP WITH TIME ZONE as TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • An input of 12:00 noon on March 7 this year in India will have its time-of-day adjusted to UTC by subtracting five and a half hours: 6:30 AM.
  • TIMESTAMP WITHOUT TIME ZONE
    • Any specified time zone or offset included with the input data is entirely ignored.
    • An input of 12:00 noon on March 7 this year in India is recorded as 12:00 on March 7 of this year with no adjustment.

The SQL standard barely touches on issues of date-time data types and behavior. So database vary widely in the handling of date-time.

3
  • 2
    further with factory (or hospital) shifts, anyone working the graveyard shift on the days of DST changeover will have their hours recorded incorrectly of it's recorded without timezone..
    – Jasen
    Commented Jan 21, 2019 at 1:47
  • I think there is a typo in the last example: 'An input of 12:00 noon on March 7 .. should be 'recorded as 12:00' (not 21:00)
    – TmTron
    Commented Jan 21, 2019 at 16:02
  • @Jasen When recording time actually worked, you are tracking a moment, a specific point on the timeline. For tracking a moment you do not use TIMESTAMP WITHOUT TIME ZONE. For tracking a moment such as when a person started and finished their work shift, you use TIMESTAMP WITH TIME ZONE. In Java code that would be ZonedDateTime shiftEnded = ZonedDateTime.of( 2020 , 1 , 23 , 2 , 0 , 0 , 0 , ZoneId.of( "Africa/Tunis" ) ) ;. Then write to database column of type TIMESTAMP WITH TIME ZONE: myPreparedStatement.setObject( shiftEnded.toOffsetDateTime() ) ; Commented Mar 22, 2020 at 18:30
33

I'd like to add another view to this, which goes against much of what's been written in the other answers. In my opinion timestamp with time zone has very little valid use cases, and timestamp without time zone should in general be preferred.

First, you must understand the "UTC everywhere" pattern, which is generally recommended for all applications that don't have very special requirements. It simply means that your application should represent all of its timestamps in UTC, everywhere, all the time. Of course, you will be showing local date/time to users, but the idea is to convert these at the very edge of your program, when rendering the view. This is the right place to combine the UTC timestamp (which you may have loaded from a database) and the user's timezone (which may have come from the browser) into a local timestamp.

If you're following this pattern, then timestamp with time zone is an anti-pattern. All this type does is make PostgreSQL perform timezone conversions when reading and writing timestamps, based on your PostgreSQL TimeZone session variable. Instead of dealing with timezones at the very edges of your application, you have introduced them into its heart, into the very communication with your database. You must take care to always have PostgreSQL TimeZone properly configured at all times, adding another unnecessary point of failure and confusion.

And for what? If you're following the UTC everywhere pattern, your application only has UTC timestamps anyway; so why ask your database to do timezone conversions on them? You can simply store them in a timestamp without time zone column, and treat it like it's always UTC. No conversions, no timezones, no complications.

EDIT 2021-10-01: After a long time, I'd like to nuance the above... It's true that the text representation of timestamp with time zone is a local timezone, and that introduces a conversion that usually isn't wanted. However, many PostgreSQL drivers read and write timestamptz as a pure UTC timestamp (in whatever representation is appropriate in the language); when that's the case, timestamptz should definitely be preferred for holding UTC timestamps.

As the maintainer of the .NET PostgreSQL driver (Npgsql), we're making this exact change in the upcoming 6.0 version: Npgsql will simply return a UTC timestamp containing the exact value as it is in the database, without any conversions (see the release notes).

13
  • 3
    I think that the proponents of the timestamptz also support the "UTC everywhere" pattern. It's just rule just gets enforced at the database level instead of only relying on app/API developers to enforce it? If you're able to enforce that practice, why not? Also, you can just enforce that all postgres connections set their timezone to UTC. Even if they don't, the ISO format will contain the tz offset. So isn't that the same thing as UTC everywhere but enforced?
    – iamnat
    Commented Aug 22, 2018 at 9:46
  • 9
    First, if your PostgreSQL TimeZone is set to anything but UTC and your are using timestamptz, your program is reading non-UTC timestamps. This is simply not the "UTC everywhere" pattern, and depending on your client language may or may not create lots of complications. Either you're UTC everywhere, or you're using local timestamps.... Commented Aug 22, 2018 at 10:04
  • 1
    Once again, it's very easy to imagine a new PostgreSQL instance being set up on some server, accidentally retaining the local machine timezone which is configured by default. Applications read from this server and get local timestamps in a totally arbitrary timezone (which the server happens to be in). Why would we want this additional complication? Commented Aug 22, 2018 at 10:11
  • 2
    It could, but then it would make even less sense to use timestamptz. The whole point of this type is to perform timezone conversions as values as read and written to PostgreSQL (internally in the database, the timestamp is always saved as UTC). Always setting the session time zone to UTC effectively disables those conversions, so why use timestamptz at all? Put another way, if the values in the database are UTC, and the values coming in and out of the database are always UTC, then why have time zone awareness at all in your database? Commented Jan 21, 2019 at 13:45
  • 1
    A very sane answer actually. When using abstractions such as JPA, everything gets converted to something like java.time.Instant anyway so timestamp without timezone is actually the preferred choice because even if someone is changing timezones on database server it will still return the correct unchanged UTC.
    – cen
    Commented Feb 11, 2020 at 17:36
4

It may seem temping to store and process dates/times in local time if your application is limited to a single time zone but I believe this to be a mistake.

When switching back from daylight savings time to standard time an hour in local time is repeated (assuming the difference is an hour). Where I live this typically happens around 2am so local time runs 01:58, 01:59, 01:00 and only advances to 02:00 at the end of the repeated hour.

If you attempt to order events by time using local time that means events from two separate hours are mingled together and do not appear in the order in which they actually happened.

By comparison UTC does not have this problem and orders cleanly. So, even when working with just one time zone, you do want the DB to store and process times in UTC and convert to/from local time for input/display. This is the behaviour of TIMESTAMP WITH TIME ZONE.

3

The date timestamp also doesn't include timezone information, yet a lot of people use it.

Of course, that of itself is not an answer.

It's valid to use timestamp and date for any timestamps and dates which are always in the same timezone, or are being stored relative to some known timezone.

If the timezone is always the same or implicit then it's more of antipattern to store it than to not store it (redundant information).

Timestamps can also be used for storing technical information such as used in application logs or for performance measurements. In this case, the timezone can also be unimportant.


Conversely, if you are designing or working on a distributed system or in any system where parts of the system will be distributed across different timezones, it might be considered to be an anti-pattern to not use timestamp with timezone, although some systems might be designed to run in one timezone, eg UTC. In this case the timezone logic may be being pushed into the application layer -- but I would consider this an anti-pattern, yes.

3
  • I understand that in certain cases it doesn't hurt to use timestamp without timezone, but does it ever buy me anything? Otherwise, why should I bother if the timestamp with timezone data type is always equally or more appropriate? Commented Feb 16, 2014 at 15:35
  • Not storing redundant information would be my main argument. I presume date arithmetic on timestamp without timezone would be faster, too, but that is probably only important if you are processing billions of rows... Commented Feb 16, 2014 at 15:52
  • 1
    @Colin'tHart timestamp and timestamptz are both stored the same way. There is no time zone information being stored in a timestamptz, but instead it is converted to UTC for storage. I'd say, always use timestamptz when the timestamps in question denote absolute time. That's all what timestamptz means. I've written about this here.
    – fphilipe
    Commented Jun 20, 2016 at 14:19
1

2 example use cases:

  1. You have a movie that will be premiered in cinemas globally on the same date, and at the exact same local time everywhere, e.g. "9am locally, regardless of where you are". Therefore actually at different times in reality... some countries/cities are going to be lucky enough and get see the movie earlier than others, depending on their local timezone offset.
  2. You run a global chain store such as 7/11 (back when the opening hours were actually normally 7am - 11pm). You've decided to post some special hours for all stores globally this Christmas day, same as above... e.g. "9am" just means "9am locally, everywhere... regardless of where you are".

Programming since the 90s... I don't think I've ever actually had a use case where WITHOUT would have been preferable over TIMESTAMPTZ, assuming I had the choice between both.

1

Future Bookings,

You want to allow people to book a time and date in the future and not be have bookings jump around when the politicians suddenly decide to change to daylight savings rules, or timezone on you.

If the booking are only close enough to present that you can trust politicians not to trash your data this may not be an issue.

Everything else is probably better represented in timestamptz

Fortunately they never make retroactive changes to DST, so using timestamtz for recording historical data is works well (especially for events in the doubled hour)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.