There were quite a few questions about saving datetime & timezones info in DB but more on the overall level. Here I'd like to address a specific case.
System specs
- We have an Orders system database
- It is a multi-tenant system where tenants can use arbitrary timezone (it is arbitrary but single timezone per tenant, saved in Tenants table once and never changes)
Business rule needed to be covered in DB
- When tenant places an Order into the system, order number gets computed based on their local datetime (its not literally a number but some kind of an identifier like
ORDR-13432-Year-Month-Day
). Precise calculation is not important for the moment, it's just important that it's dependant on tenants local datetime - We also do want to be able to select all Orders, on the system level, placed between some UTC datetimes regardless of the tenant (for general system statistics/reporting)
Our initial idea
- Our initial idea was to save UTC datetime across whole DB and, of course, keep tenants timezone offset relative to UTC and have application that consumes DB always convert datetimes to UTC so that DB itself always operate with UTC.
Approach 1
Saving local tenants datetime would be nice per tenant but then we have problem with queries like:
SELECT * FROM ORDERS WHERE OrderDateTime BETWEEN UTCDateTime1 AND UTCDateTime2
It's problematic because OrderDateTime
in this query means different moment in time, based on tenant. Of course, this query might include join to Tenants
table to get local datetime offset which would then calculate OrderDateTime
on the fly to make adjustments. It's possible, but not sure if it's a good way to do it?
Approach 2
- On the other hand, when saving UTC datetime, then when we do calculation of OrderNumber since the day/month/year in UTC might differ from the one in local datetime
Let's take extreme example; let's say tenant is 6 hours ahead of UTC and his local datetime is 2017-01-01 02:00
.
UTC would be 2016-12-31 20:00
. Order placed at that moment should get OrderNumber 'ORDR-13432-2017-1-1'
but if saving UTC it would get ORDR-13432-2016-12-31
.
In this case, at the moment of creating Order in DB, we should get UTC datetime, tenants offset and compile OrderNumber based on recalculated tenants localtime but still save DateTime column in UTC.
Questions
- What is the preferred way of handling this kind of situation?
- Is there a nice solution with saving UTC datetimes because that one would be pretty nice for us because of the system-level reporting?
- If going with saving UTC, is Approach 2) good way to handle those cases or is there some better/recommended way?
[UPDATE]
Based on comments from Gerard Ashton and Hugo:
Initial question was not clear with respect to the detail if tenant can change timezone or not and what happens if political authority changes the timezone properties or some terirory's timezone. Of course that is of an extreme importance, but it is not in the center of this question . We might address that in a separate question.
For the sake of this question, lets assume tenant will not change location. Timezone properties or timezone itself for that location might change and those changes will be handled in the system separately from this question.