DEV Community

Cover image for Date and Timezone oddities on Node, Browser and Lambda
Davide de Paolis
Davide de Paolis

Posted on • Edited on

Date and Timezone oddities on Node, Browser and Lambda

If I run

node
> new Date()
Enter fullscreen mode Exit fullscreen mode

in the terminal, I get this timestamp: 2019-03-28T13:37:22.081Z
while if I run new Date() in the browser console I will get
I get this timestamp: Thu Mar 28 2019 14:37:39 GMT+0100 (Central European Standard Time) which is more accurate, since I am in Hamburg, which is 1h+.

If I bring back the clock of my pc 5 hours and run the same code I get 2019-03-28T08:43:26.895Z from node and Thu Mar 28 2019 09:43:14 GMT+0100 (Central European Standard Time) from the browser console.

back to the future

This makes perfect sense - nothing special here. (even though I was slightly surprised by the different outputs on the Date constructor in the browser and in nodeJs).

What will the Timezone be when I run my code on Lambda? Will it be different if the code runs on containers in different regions?
Of course - luckily - not!

No matter where the lambda is running it will always have the UTC timezone.

This can be tested by running console.log(process.env.TZ). TZ is a Lambda reserved env variable which will print :UTC.

Therefore ( unless I messed around with my pc clock) new Date() on my deployed Lambda will give me the same time as when it runs locally.

Even here nothing really surprising.
boring..

What screwed my code this morning was Date.toLocaleDateString()

Since we had to pass to a RestAPI a query param with a date in the format YYYY-MM-DD we were using d.toLocaleDateString('de-DE') and then manipulating the output to format it as expected. It was a silly method but we didn't want to be bothered importing Moment.js for this tiny thing.

Everything was working fine, I had many unit tests proving different dates and formats. Then after deploying ( on a Development Stage, of course ): BAM!, nothing works... API was rejecting my request.

Then i realized that the format was broken because on AWS the toLocaleDateString behaves differently. Well, it is not just AWS, it is Node that behaves differently from the Browser, and how the toLocaleDateString works on Node depends on the Node version and the icu built with it.

On my machine

    const d = new Date()
    console.log(d)
    console.log("toLocaleDateString('')",d.toLocaleDateString())
    console.log("d.toLocaleDateString('en-US')",d.toLocaleDateString('en-US'))
    console.log("d.toLocaleDateString('de-DE')",d.toLocaleDateString('de-DE'))
Enter fullscreen mode Exit fullscreen mode

was printing :

2019-03-28T09:04:31.507Z
toLocaleDateString('') 3/28/2019
d.toLocaleDateString('en-GB') 28/03/2019
d.toLocaleDateString('en-US') 3/28/2019
d.toLocaleDateString('de-DE') 28.3.2019
Enter fullscreen mode Exit fullscreen mode

while on the lambda

2019-03-28T14:05:14.952Z
toLocaleDateString('') 2019-3-28
d.toLocaleDateString('en-GB') 3/28/2019
d.toLocaleDateString('en-US') 3/28/2019
d.toLocaleDateString('de-DE') 2019-3-28
Enter fullscreen mode Exit fullscreen mode

Unfortunately I did not have the time to further investigate how the intl module of node works based on the Build, nor how to use the full-icu package as mentioned in [this issue]https://github.com/nodejs/node/issues/8500), so in the end we dropped the reverseFormat method and we simply grabbed each value individually to construct the string we wanted:
d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate()).

Not nice, but sometimes you also have to accept the fact and meet with your deadlines ( and the reverse method was not that smart anyway..)

To recap:

  • No matter which region your Lambda runs on - timezone will always be UTC.
  • Due to the ICU build in the node version running toLocaleDateString might have unexpected output.
  • If you want to get the current time on a specific timezone then you have to use moment-timezone ( overwriting process.env.TZ does not have any effect on the timezone used by Date)

Hope it helps.

Top comments (1)

Collapse
 
bisonfute profile image
bisonfute

thanks for clarifying