DEV Community

Cédric Teyton for Packmind

Posted on • Edited on

Handle dates and time zone in your code

I'm late

Software developers often have to handle dates. Honestly, I’m not sure this is their favorite part of their job 😉 Indeed, date manipulation can lead to various problems of date computation, such as bad management of time zones. This article provides some tips to avoid common issues and handle date operations in your source code. We’ll cover examples with JS dates but the principles introduced here can be applied in any language.

Main Tip : Encapsulate date operations

First of all, you should encapsulate all date operations in a class, a service, or a separate module. Trust me: this will definitely save you a lot of time (no pun intended) even if it seems like a waste at first. Such a module will provide all the functionalities needed in your code regarding date operations. No more, no less. Do you need to perform operations with time zones? The module does it for you. Do you need to compute a date? The module does it for you. Do you need to calculate which of the dates in a list is the most recent? Again, the module does it for you. You get the idea. We will recommend you to only use functionalities from this module. Developers shouldn’t have to write source code that performs date operations anywhere else.

This approach is similar to hiding database implementations of object repositories and brings more flexibility. Indeed, in the same way a repository gives you an item without needing to know about how the information is actually stored, here you can request a date without needing to know the implementation specifics of the library used.

You may (should?) rely on libraries dedicated to that purpose, such as Moment for JS code, or Joda for Java. This is definitely a good idea, in the same way that you should use a database tool (MySQL, Mango, Redis, Etc.). However, calls to these APIs should only appear inside your date module and nowhere else in your code. This will improve your program’s testability and let you focus on setting up a test suite for your module.

Illustration with JS Dates

Here is an extract of a TimeHelper class managing date with Moment, where we can observe that Moment usage is hidden from outside the class :

public isSameDate(other: TimeHelper): boolean {

    let thisDate: moment.Moment = this.toMoment;
    if(this._isNextDay){ thisDate.subtract(1, "day"); }

    let otherDate: moment.Moment = other.toMoment;
    if(other._isNextDay){ otherDate.subtract(1, "day"); }

    return thisDate.isSame(otherDate, "date");
}
Enter fullscreen mode Exit fullscreen mode

Always check dates and TZ

Assume you develop a calendar application written without taking time zones into account and using a generic date management library (datetime in Python, date in JS/TS, std::chrono in C++, etc.). If you decide to export the application across the world (even in France, which is on the TZ of UTC-10 (Tahiti) until UTC+11 (New Caledonia)), if you don’t have date encapsulation, it is necessary to find ALL dates and enrich them with time zone information.

Also, anytime you ask a user input containing day and hour, you should always wonder if asking for the Time Zone is necessary. If you’re based in Paris and book for a movie in London for 7pm, you should consider 7pm on London TZ. Also, it’s usually a bad practice to store date format in your DB within any TZ information. You need to know where your 7pm is on Earth !

TimeZone

Control your date formats

Secondly, another best practice is also to limit the display formats of the dates. It seems quite intuitive that all dates and schedules should look the same across your application. To facilitate this, we can create an enumeration, or global variables, containing the list of different formats used in the application. This way, if we want to use a format, we always have them at hand, and if we don’t find the one we wanted to use, it’s undoubtedly a bad idea to use it. Or at least, this should be validated by your customer.

Here is an example of enumeration using dates :

export enum TimeFormats {
    HH_mm =  "HH:mm",
    HH_h_mm = "HH[h]mm",
    HH_mm_ss = "HH:mm:ss",
}

export enum DateFormats {
    DD_MM_YYYY = "DD/MM/YYYY",
    YYYY_MM_DD = "YYYY-MM-DD",
    dddd_LL = "dddd LL",
    DD_MM = "DD/MM",
    dddd_DD_MMMM = "dddd DD MMMM",
    dddd_DD_MMMM_YYYY = "dddd DD MMMM YYYY",
    ddd_DD_MMM_YYYY = "ddd DD MMM YYYY"
}
Enter fullscreen mode Exit fullscreen mode

Anticipate the situation

Thirdly, the best way to get by with date management is to prepare the software. Indeed, the sooner we become aware of the use cases of dates, the sooner it is possible to implement them appropriately in the project. It can even be interesting to create this module, this service, this class from a prototype/MVP. Because you never know, some people already saw an MVP going into production… ;)

The last recommendation is to gather all best practices related to date management into Packmind to make it clear for anyone in the team and any newcomer.

Top comments (0)