DatePickers: working with Timezones

Nnabueze Uhiara
3 min readNov 8, 2020

Some users on an app I built complained that when they selected their birth date, the date displayed(and subsequently submitted to the backend) was always off by 1 day. It, however, worked fine for me.

It happened to a few other users so a pattern was established; it definitely had to be an error from my end. Since it worked fine for me, I had to narrow down possible differences between those users’ environment and mine. One stuck out: Timezone. They were all in Canada.

Debugging to find the cause

I tried to reproduce the error by changing my device timezone to Canada Vancouver(GMT-8). A picture they say is worth a thousand words, so here are some screenshots detailing my debugging journey:

  1. When I selected November 3, 2020, this was what was returned on the callback. Notice the humanReadableDate is off by 1 day, also that the returned timestamp is 1604361600000
The humanReadableDate is off by 1 day! Bug reproduced 🎊

2. I copied this timestamp over to EpochConverter, this was the result.

the timestamp shows the right date
UX (What the user sees)

It was then obvious that the bug was introduced by my dateFormatter. The dateFormatter used the user’s timezone to format the GMT/UTC timestamp returned by the datePicker.

The GMT/UTC deviation in Vancouver is -8 hours. The timestamp date is November 3, 2020, 12:00:00 AM (GMT/UTC). Since Vancouver lags GMT/UTC by 8 hours, time there will be November 3, 2020, 12:00:00 AM minus 8 hours = November 2, 2020, 4:00:00 PM, hence the date returned by the dateFormatter.

Fixing the bug

Once the cause was found, the fix was pretty much easy: set a fixed timezone (UTC/GMT) that will be used by the dateFormatter. This I did.

Here are more screenshots detailing the fixing process:

DateFormatter before the fix. No set timezone so it uses the user’s default timezone.

DateFormatter with the fix applied. Timezone is now set to UTC, which will be used by the formatter regardless of user’s timezone.

DateFormatter with the fix

Testing

The fix has now been applied and it is time to test. As usual, I will share screenshots of the tests.

Bug-fix verified: HumanReadableDate now shows the correct date
UX after the fix has been applied

You can also write tests to catch/guard against the bug next time.

I have always known to guard against timezone bugs when working with dates but this one was unexpected. I guess it was because I assumed(wrongly) that the time part of the date would not matter, since I was not directly interested in its value. The implication of this bug gets worse if you are, like me, sending the humanReadableDate value to the server instead of the timestamp.

This may be useful to someone. I found this out while debugging this bug. To get the deviation of a timezone off UTC/GMT, use this:

As always, comments, suggestions and corrections are most welcome. Thanks for reading.

--

--