Time Zone Offset Issue in freeCodeCamp's Exercise Tracker Project

Introduction

Part of the curriculum at freeCodeCamp is their Back End Development and APIs Projects. The projects are straightforward MERN stack projects with fairly well defined interfaces that have to be implemented to pass tests ran over the internet to verify behavior. So, you can stick to the MERN stack and implement the back end in Express and friends or you can branch out and implement it in Ruby on Rails, Django, Flask, or whatever as long as the behavior is correct. They also make good starting points for React or Vue front ends since they result in simple, easy to use APIs.

Timezone Issues

All the projects have their quirks, but the Exercise Tracker has a very popular one. The purpose is to implement an exercise log that users can use to track what exercise they may have done on a given date. The tests check the format of the data and responses, as expected, but also try to verify dates. This often provides students with their first taste of why dates and times are so difficult.

The problem with using a date for a record is that JavaScript will use midnight (local time) as the time part of a new Date() object if no time is specified. If we are naively recording only the date (because of project specifications), then those dates get the midnight, local time, as their time. This works as long as all the computers involved are in the same time zone.

Because the tests are actually ran from the submitting user's browser, over the internet, that means that the tests will run with the user's local time against a hosting server (repl.it for instance) using the server's local time (almost always UTC). This means that unless the user is using UTC as local time, then for part of every day the local date and UTC date are different and this part of the day corresponds to the timezone offset. For instance, in US Central Standard Time (-6), that means the local date and UTC date are different from 18:00 to midnight. Since the dates are different, that means that all project tests that check the date will fail during that time.

Solutions

There are two options to work around the problem involving matching the local and UTC dates. First, you can change your local time to UTC to run the tests. Depending on your setup, this may be the easiest. There are extensions that can change just the timezone in the browser, so you may not even need to change the system time. Second, you can run the tests during the part of the day when the local date and UTC date are the same. It's a low overhead solution, but inconvenient if you want to run the tests now and now is not the right time.

However, best thing to do is to avoid the workarounds completely and use this as a good learning experience for handling dates. Since the problem stems from not having the correct times associated with our dates, the solution is obvious: include the time. So, when you design an API on your own and want to store the date for a record, store it as a datetime (even if all you care about is the date). You will have the date and can ignore the time, but you gain awareness (in JavaScript anyway) of the timezone and the offset problem disappears. If you are using a framework (Django) that allows naive datetimes (ignorant of time zone), make sure you either use aware datetimes or avoid the naive ones unless you are sure you need them.

Conclusion

Dates and times are deceptively difficult in programming for such a quotidian concept. People hate JavaScript's Date() object and there are proposals for more advanced interfaces. Python has multiple different interfaces to dates and times. A large chunk of the C standard library involves dates, times, and time zones. Try to make your life as easy as possible and include as much data as possible. Use aware datetimes, even if you just need part of the data, and you will be able to work around many more issues that if you don't.