How to create time constants in JavaScript in a performant way

Ciprian on Thursday, April 7, 2022 in JavaScript Time & Date

NEW! Learn JavaScript by example. Code snippets, how-to's and tutorials. Try now!

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

5 comments on “How to create time constants in JavaScript in a performant way

  1. Version 3 has a typo that will cause an error, but also getters aren’t inherently more efficient. They don’t memoize or cache the result from the previous calculation. Actually, they’re less performant since you’re adding a layer of complexity on top of the calculation.

    1. I can’t see the typo and the code runs for me. What am I missing?

      Regarding the getters, you may be right, but in any standard scenario, I would prefer the third version due to its readability. I’d love to see a speed comparison of the 3 versions.

  2. https://gist.github.com/scarf005/65e7954ca15bdff5f6c4e11052668475

    I’ve benchmarked each version in https://gist.github.com/scarf005/65e7954ca15bdff5f6c4e11052668475 .

    to my surprise, version 3 was approximately 7 times slower, not faster than version 1. my suggestion is to use local variables.

    const MILLISECOND = 1
    const SECOND = 1000 * MILLISECOND
    (…)

    export const TIME = { MILLISECOND, SECOND, MIN, HOUR, DAY, WEEK, MONTH, YEAR }

    this way, both performance and readability can be satisfied.

Leave a Reply

Your email address will not be published. Required fields are marked *