There’s not much else that tops the list of things I struggle with in software development than dates and time zones. You’ll get to a point where you think you understand it all then you read Falsehoods programmers believe about time zones and you realise that you didn’t really know much at all, and indeed some of what you thought you knew probably isn’t correct, as was/is my case.
I’m from England generally speaking we have two timezones, GMT (UTC+0) and BST (UTC+1). We have a Daylight saving time (DST) which means our UTC offset changes twice a year. This year Daylight saving time started on the 27th of March and it’ll end on the 30th of October.
The common conversions I need to make when coding or debugging are from UTC to my local time and vice versa. And when I need to make these conversions the data is usually in one of the following formats:
- Unix timestamp
- ISO 8601
- Local Datetime
- UTC Datetime
I need a tool which will take in as input any of these formats and convert it to all of the other formats so I don’t have to think about it.
Unix timestamp converter
Very often — when inspecting a JWT as an example — I’ll have a Unix timestamp that I need to figure out what date/time it represents. Unfortunately I’m not quite smart enough to be able to compute the date in my head from the number of seconds since epoch, so I’ll need to write some code to do it for me.
All of the code I’ve actually written for my electron application is using Vue.js. I’m going to drop the Vue.js syntax for the sake of simplicity here.
Let’s assume that the Unix timestamp we have is in ms.
Converting a Unix timestamp to a date:
// eg 1660415677393 const localDate = new Date(unixTimestampMs).toLocaleString(); // 13/08/2022, 19:34:37
Converting a Unix to a UTC DateTime string:
// eg 1660415677393 const localDate = new Date(unixTimestampMs).toUTCString(); // 13/08/2022, 19:34:37
Converting a Unix timestamp to an ISO string
// eg 1660415677393 const isoString = new Date(unixTimestamp).toIsoString(); // 2022-08-13T18:34:37.393Z
All pretty simple so far.
Datetime local converter
This is where it starts to get a little bit more tricky. First off, we have to create a Date which is usable in a
.toISOString() function on the Date object, but that’ll give you the UTC datetime rather than your local.
To combat this we create a Date object, minus the timezone offset and then get the ISO string. Once we have the ISO string I’m only taking the first 19 characters, which looks something like:
let now = new Date(); now.setMinutes(now.getMinutes() - now.getTimezoneOffset()); const dateTimeLocal = now.toISOString().slice(0, 19);
To explain this a little more…
let now = new Date(); // Sat Aug 13 2022 20:30:46 GMT+0100 (British Summer Time) now.getTimezoneOffset() // -60 (we're 1 hour ahead of UTC) now.getMinutes() // 30 (it's half past 8) now.getMinutes() - now.getTimezoneOffset() // 90 now.setMinutes(now.getMinutes() - now.getTimezoneOffset()); // this adds an hour // Sat Aug 13 2022 21:30:46 GMT+0100 (British Summer Time) // so at this point we are UTC+2, so that when we do the ISOString() is keep us at UTC+1 const dateTimeLocal = now.toISOString().slice(0, 19); // '2022-08-13T20:30:46'
The conversion from the local date to the UTC values is much the same as in the previous example.
Datetime UTC converter
This is probably the use case I require the least, usually, if I have a UTC date it’s either as an ISO string or a Unix timestamp, but I thought I’d add it for completeness.
Remember the issue we had before when supplying the datetime input? Well, this time we don’t need to make the conversion because converting to UTC when doing the
.toISOString() is exactly what we want.
When a user enters a new UTC datetime I need to convert it back to local time. I need to follow the same steps as before, so that when I call
toUTCString() it behaves correctly. Here’s a sample of the code for when the input has been updated:
let newDate = new Date(dateTimeUTC.value); newDate.setMinutes(now.getMinutes() - now.getTimezoneOffset()); dateTimeUTCTimestamp = Math.floor(newDate.getTime() / 1000); dateTimeUTCTimestampMs = newDate.getTime(); dateTimeUTCISO = newDate.toISOString(); dateTimeUTCDateTime = newDate.toUTCString(); dateTimeUTCDateTimeLocal = newDate.toLocaleString();
If you’re interested in what the UI looks like at the moment — it’s still a work in progress, and this is very much in a draft state:
And that’s pretty much all there is to it, if you liked this blog then please sign up for my newsletter and join an awesome community!