Skip to content

Instantly share code, notes, and snippets.

@meyt
Last active June 2, 2024 03:32
Show Gist options
  • Save meyt/c5dc41c8ec9500ea9755e6e223bebeda to your computer and use it in GitHub Desktop.
Save meyt/c5dc41c8ec9500ea9755e6e223bebeda to your computer and use it in GitHub Desktop.
Convert ISO8601 UTC string to UNIX timestamp and vice versa in Javascript
const epoch = 1970
const dayInSeconds = 86400
const hourInSeconds = 3600
const minuteInSeconds = 60
const dayInHours = 24
const toInt = v => parseInt(v)
const isLeap = v => ((v % 4 == 0) && (v % 100 != 0)) || (v % 400 == 0)
const pad = (v, n = 2) => v.toString().padStart(n, '0')
function ts2iso(ts) {
const seconds = ts % minuteInSeconds
const minutes = parseInt(ts / minuteInSeconds) % minuteInSeconds
const hours = parseInt(ts / hourInSeconds) % dayInHours
const daysInMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
let days = parseInt(ts / dayInSeconds) + 1
let years = epoch
let months = 1
while (days > 365) {
if (isLeap(years)) {
if (days === 366) break
days -= 366
} else {
days -= 365
}
years++
}
if (isLeap(years)) daysInMonths[1] = 29
while (days > daysInMonths[months - 1]) {
days -= daysInMonths[months - 1]
months++
}
const date = `${pad(years, 4)}-${pad(months)}-${pad(days)}`
const time = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`
return date + 'T' + time + 'Z'
}
function iso2ts(iso) {
const [date, time] = iso.split('T')
const [year, month, day] = date.split('-').map(toInt)
const [hour, minute, second] = time.replace('Z', '').split(':').map(toInt)
const daysInMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
let ts = 0
for (let i = epoch; i < year; i++) {
ts += (isLeap(i) ? 366 : 365) * dayInSeconds
}
if (isLeap(year)) daysInMonths[1] = 29
for (let i = 0; i < month - 1; i++) {
ts += daysInMonths[i] * dayInSeconds
}
ts += (day - 1) * dayInSeconds
ts += hour * hourInSeconds
ts += minute * minuteInSeconds
ts += second
return ts
}
const tests = {
"10": "1970-01-01T00:00:10Z",
"63072000": "1972-01-01T00:00:00Z",
"315532800": "1980-01-01T00:00:00Z",
"647135999": "1990-07-04T23:59:59Z",
"951825600": "2000-02-29T12:00:00Z",
"1273903628": "2010-05-15T06:07:08Z",
"1609459199": "2020-12-31T23:59:59Z",
"1709164800": "2024-02-29T00:00:00Z",
"1909074600": "2030-06-30T18:30:00Z",
"2214172862": "2040-03-01T00:01:02Z"
}
Object.entries(tests).sort((a, b) => a[0] - b[0]).forEach(([ts, iso]) => {
ts = parseInt(ts)
const iso2 = ts2iso(ts)
const ts2 = iso2ts(iso)
if (iso2 !== iso) console.log('ts2iso mismatch ', ts, iso, iso2)
if (ts2 !== ts) console.log('iso2ts mismatch ', iso, ts, ts2)
})
console.log('done')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment