If I run
node > new Date()
in the terminal, I get this timestamp: 019-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.
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.
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'))
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
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
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..)
- 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.