JavaScript中使用luxon处理时区特定日期出现解析错误
问题原因
该异常是服务器环境默认区域设置(Locale)与本地开发环境不一致导致的12小时制上午/下午标识解析失败,具体逻辑如下:
- 你使用的
tt格式符用于匹配12小时制的AM/PM标识,解析规则完全依赖当前生效的locale:Mac本地默认locale为英文环境,tt可以正常匹配am/pm字符串;而服务器的默认locale为非英文(大概率是孟加拉语本地locale),tt对应的上午/下午标识不是am/pm,导致解析时直接忽略am/pm标识,将08:00:00识别为24小时制的达卡时间8点,减去6小时时差后得到UTC时间14点,和你观测到的异常结果完全吻合。 - 额外问题:你当前使用的格式串
yyyy-MM-dd tt和输入的字符串格式不匹配,输入字符串包含hh:mm:ss时分秒部分,格式串未声明该部分,也会导致时分秒解析异常。
修复方案
方案1:显式指定解析用locale与完整格式串(最优)
修改代码为如下形式,强制指定英文locale匹配am/pm标识,同时补全格式串匹配时分秒,完全不受服务器系统设置影响:
return DateTime.fromFormat(startStr, 'yyyy-MM-dd hh:mm:ss a', { zone: 'Asia/Dhaka', setZone: true, locale: 'en-US' }).toJSDate();
修改后2021-11-14 08:00:00 am会被正确解析为达卡时区8点,转换为UTC时间就是你预期的2021-11-14T02:00:00.000Z。
方案2:统一输入格式(从源头规避问题)
如果可以调整输入的startStr、endStr的生成规则,优先使用24小时制格式,或者直接生成ISO 8601标准格式的日期字符串,完全避免AM/PM这类和locale绑定的标识,解析时不会出现环境差异问题。
问题验证方法
可以在服务器环境执行以下代码确认locale差异:
console.log(DateTime.now().setLocale('default').toFormat('tt'));
如果输出不是am/pm,即可确认是默认locale不匹配导致的问题。
内容的提问来源于stack exchange,提问作者Ahsan Aasim
相关产品推荐
相关产品推荐

