I’m working on an app that can potentially be used across multiple time zones (at the very least, if users go on vacation and access the app from another timezone). I’ve never tackled this issue before, but I know it’s pretty complex, so I wanted to post my design here with the hopes of getting some feedback.
I use Postgres.
For example purposes, I want to talk about the To-Do Item
context, since it’s a fairly common thing that a lot of people have experience with.
The desired behavior from the perspective of the user:
- When creating/editing a to-do item, the user can provide a due date, a due date and due time, or neither.
- If the user is located on the East Coast when they create the to-do item, someone who views that item on the West Coast (including potentially the same user) should see the due date and time in their own timezone. They should also see the timezone the item was created from, if it is different from their current timezone. Microsoft Outlook has a good example:
The timezone snippet displays for me because I’m currently on Central Time.
Anyways, here’s the design I came up with:
- When the user first signs up, I capture the name of their current timezone (e.g. “America/Chicago”) using JavaScript and store it in a
default_timezone
text column. - Whenever the user logs into the app from that point forward, if the app detects a discrepancy between the account’s
default_timezone
and the browser’s timezone, it displays a warning:
They can ignore this (which makes the prompt go away for a week) or go to their account settings and pick the new timezone name from a dropdown.
Now, let me talk about the to_do_items
table and associated context. Along with the typical fields (event name, description, etc.) it has three columns:
due_date (type: date)
due_time (type: time without timezone)
due_time_tz (type: text)
I originally had the first two columns as a single datetime column, but since the time field is optional, it introduced some complexity when doing the conversions while inserting/updating so I split them up. I noticed this is different from how many calendar apps handle it - for example, in Outlook if you don’t enter times, they default to 12:00 AM.
Anyways, when the user is creating a to-do item, the browser also sends the user’s current timezone name, which I stick into the due_date_tz
column. Then, when the item is being viewed, I use moment.js and moment-timezone.js to look at the date, time and timezone on the object and display their combined result in the user’s current timezone. For example, “9-5-2019 1:00 AM - America/Chicago” is displayed as “9-4-2019 11:00 PM” when viewed from America/Los_Angeles.
Based on some cursory testing, this seems to work well. But cursory testing is not a substitute for real usage, especially over long periods when timezones can change! My question is, is this design usable, or is it totally and irreparably stupid?
I thought about a few ways in which it might be made better:
- Combine the
due_date
anddue_time
back into a singledue_date_time
field, and make it atimestamp with time zone
column. - If the user is submitting an item without a due time, automatically default the time to 12:00 AM.
- Take the submitted due date and due time, along with the user’s current timezone, and convert them to UTC on the server (e.g. using Timex) before storing in the
due_date_time
field. If a timezone is not provided during submission (for whatever reason), fall back to thedefault_timezone
on the user’s account.
Thoughts?