I have this so far:
import * as chrono from 'chrono-node'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
let selectedInput = 'pst'
let selectedOutput = 'est'
let inputDateString = '10pm'
// set timezone reference point to PST
dayjs.tz.setDefault(selectedInput)
const inputDate = chrono.parseDate(inputDateString)
const utc = inputDate?.toISOString().replace(/Z$/, '')
const computedInputDate = utc
? dayjs(utc).tz(selectedInput)
: undefined
const outputDateString = computedInputDate
? dayjs(computedInputDate)
.tz(selectedOutput)
.format('h:mma on MMM D, YYYY')
: undefined
dayjs.tz.setDefault() // reset default timezone
console.log('output:', outputDateString)
I am using dayjs timezone and chrono-node (for the natural language time parsing feature). So in year 2024 on day Jan 31, you type 10pm (that is, you are saying "10pm Jan 31 2024 PST"), I would expect to see 1:00am on Feb 1, 2024 in the logged output, but instead I am seeing 9:00am on Feb 1, 2024, what am I doing wrong?
How do you start the time reference point from a particular timezone, and then how do you convert it to the other different timezone? Either using Dayjs (what I'm using), or some other library / native function would be fine.
If I instead remove the UTC conversion stuff, and go with this:
import * as chrono from 'chrono-node'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
let selectedInput = 'pst'
let selectedOutput = 'est'
let inputDateString = '10pm'
// set timezone reference point to PST
dayjs.tz.setDefault(selectedInput)
const inputDate = chrono.parseDate(inputDateString)
const computedInputDate = inputDate
? dayjs(inputDate).tz(selectedInput)
: undefined;
const outputDateString = computedInputDate
? dayjs(computedInputDate).tz(selectedOutput).format("h:mma on MMM D, YYYY")
: undefined;
dayjs.tz.setDefault() // reset default timezone
console.log('output:', outputDateString)
I get the correct 1:00am on Feb 1, 2024.
But if I reverse the timezones (EST -> PST), and plug in 10pm, I should see 7:00pm on Jan 31, 2024 (PST), but I see 10:00pm on Jan 31, 2024, so my calculations aren't quite right in either direction.
import * as chrono from 'chrono-node'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
dayjs.extend(utc)
dayjs.extend(timezone)
let selectedInput = 'est'
let selectedOutput = 'pst'
let inputDateString = '10pm'
// set timezone reference point to PST
dayjs.tz.setDefault(selectedInput)
const inputDate = chrono.parseDate(inputDateString)
const computedInputDate = inputDate
? dayjs(inputDate).tz(selectedInput)
: undefined;
const outputDateString = computedInputDate
? dayjs(computedInputDate).tz(selectedOutput).format("h:mma on MMM D, YYYY")
: undefined;
dayjs.tz.setDefault() // reset default timezone
console.log('output:', outputDateString)
How do I get this working going forward or backward in timezones given an input timezone, output timezone, and input time (natural language)?
Update: Tried Luxon
Tried luxon but same results pretty much.
const time = '10pm'
const selectedInput = 'EST'
const selectedOutput = 'PST'
const inputDate = chrono.parseDate(time, { timezone: selectedInput })
const outputDate = inputDate
? DateTime.fromJSDate(inputDate, { zone: selectedInput }).setZone(
selectedOutput,
)
: undefined
const outputDateString = outputDate
? `${outputDate.toFormat('h:mm')}${outputDate
.toFormat('a')
.toLowerCase()} on ${outputDate.toFormat('MMM d, yyyy')}`
: undefined
// says 10pm instead of 7pm
Even with IANA location-based timezones, same issue:
const inputDate = chrono.parseDate(time, {
timezone: 'America/Cancun',
})
const outputDate = inputDate
? DateTime.fromJSDate(inputDate, {
zone: 'America/Cancun',
}).setZone('America/Los_Angeles')
: undefined
const outputDateString = outputDate
? `${outputDate.toFormat('h:mm')}${outputDate
.toFormat('a')
.toLowerCase()} on ${outputDate.toFormat('MMM d, yyyy')}`
: undefined
// says 10pm, when it should say 7pm.
Using luxon, this seems to work:
I am still open to seeing a better more robust solution though.