How to create time constants in JavaScript in a performant way

on in JavaScript Time & Date
Last modified on

A recent project of mine required time constants, and instead of opting for an additional library for just 10 or 20 lines of code, I wrote my own. Here is the first version:

// Version 1
const TIME = {
    MILLISECOND: 1,
    SECOND: 1000,
    MIN: 1000 * 60,
    HOURS: 1000 * 60 * 60,
    DAY: 1000 * 60 * 60 * 24,
    WEEK: 1000 * 60 * 60 * 24 * 7,
    MONTH: 1000 * 60 * 60 * 24 * 30,
    YEAR: 1000 * 60 * 60 * 24 * 365
}

Unlike PHP or MySQL, though, where constants are built in, JavaScript needs to calculate them every time, so, let’s lose the readability and pass the final value to each object:

// Version 2
const TIME = {
    MILLISECOND: 1, // 1
    SECOND: 1000, // 1000 * 1
    MINUTE: 60000, // 1000 * 60
    HOUR: 3600000, // 1000 * 60 * 60
    DAY: 1000606024, // 1000 * 60 * 60 * 24
    WEEK: 7004242168, // 1000 * 60 * 60 * 24 * 7
    MONTH: 100060602430, // 1000 * 60 * 60 * 24 * 30
    YEAR: 365221198760 // 1000 * 60 * 60 * 24 * 365
}

It’s not as readable as before and, honestly, it bothers me a bit. Also, are you sure those values are correct? Maybe they are, because you used a calculator, but even so, human error is a thing. So, because in JavaScript you can’t refer to a property of an object before you have initialized that object, a getter is needed.

Sometimes it is desirable to allow access to a property that returns a dynamically computed value, or you may want to reflect the status of an internal variable without requiring the use of explicit method calls. In JavaScript, this can be accomplished with the use of a getter.

MDN Web Docs

This way, you can get the object reference within itself:

// Version 3
const TIME = {
    MILLISECOND: 1,
    get SECOND() { return 1000 * this.MILLISECOND },
    get MINUTE() { return 60 * this.SECOND },
    get HOUR() { return 60 * this.MINUTE },
    get DAY() { return 24 * this.HOUR },
    get WEEK() { return 7 * this.DAY },
    get MONTH() { return 30 * this.DAY },
    get YEAR() { return 365 * this.DAY }
}

Calculations are made here, but significantly less than in version 1 and the code is more readable than version 2. It’s still approximately 7 times faster than version 1, and, combined with modern browsers’ capabilities, production ready.

How to use

As you can see in version 3, you use the constants by calling the object and one of its properties:

let my_string = 'A day has ' + TIME.DAY + ' milliseconds';

Note that all constant calls return milliseconds. You could say, for example:

let my_string = 'A day has ' + TIME.DAY / TIME.HOUR + ' hours';

Related posts