如何在JavaScript/Dayjs中正确实现含自然语言解析的跨时区时间转换
自然语言时间解析与时区双向转换问题
初始代码与问题
使用chrono-node(自然语言时间解析)、Dayjs及timezone插件实现时区转换,初始代码如下:
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' // 设置默认时区为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() // 重置默认时区 console.log('output:', outputDateString)
在2024年1月31日,输入10pm(表示该日晚上10点PST),预期输出应为1:00am on Feb 1, 2024,但实际输出却是9:00am on Feb 1, 2024。
移除UTC转换后的单向有效、双向失效
移除UTC转换部分后,代码如下:
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' // 设置默认时区为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() // 重置默认时区 console.log('output:', outputDateString)
此时得到了正确的1:00am on Feb 1, 2024,但反转时区(EST→PST)时出现错误。反转时区的代码如下:
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' // 设置默认时区为EST 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() // 重置默认时区 console.log('output:', outputDateString)
输入10pm(EST),预期应显示7:00pm on Jan 31, 2024(PST),但实际显示10:00pm on Jan 31, 2024,双向转换均存在问题。
尝试Luxon后的同样问题
尝试使用Luxon库,结果仍存在相同问题,代码如下:
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 // 输出10pm而非预期的7pm
即使使用IANA基于位置的时区,问题依旧:
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 // 输出10pm而非预期的7pm
核心疑问
给定输入时区、输出时区和自然语言输入时间,如何实现正确的双向时区转换?
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

