为何Temporal.Now.zonedDateTimeISO()无法在Intl.DateTimeFormat中正常使用?
你碰到的这个问题很常见——目前Intl.DateTimeFormat.prototype.format还不直接支持Temporal.ZonedDateTime实例,尽管它已经能很好地兼容Temporal.PlainDate和Temporal.PlainTime(这两个类型实现了适配Intl API的特殊接口)。不过别担心,有两个简单的办法能搞定它:
方案1:直接使用ZonedDateTime的toLocaleString方法
Temporal.ZonedDateTime自带了toLocaleString方法,完全支持传入Intl的配置参数,效果和用Intl.DateTimeFormat是一致的,而且更直接。
修改你代码里的todayTemporalTimestamp计算属性:
const todayTemporalTimestamp = computed(() => { return Temporal.Now.zonedDateTimeISO().toLocaleString(locale.value, { dateStyle: "long", timeStyle: "long" }); });
如果你想复用已定义的temporalFormatter3,也可以这样写:
const todayTemporalTimestamp = computed(() => { const formatter = temporalFormatter3.value; return Temporal.Now.zonedDateTimeISO().toLocaleString(formatter.resolvedOptions().locale, formatter.resolvedOptions()); });
方案2:将ZonedDateTime转换为Date对象
如果你更习惯用Intl.DateTimeFormat的format方法,可以把ZonedDateTime转换为标准的Date对象——利用它的epochMilliseconds属性就能轻松实现:
const todayTemporalTimestamp = computed(() => { const zonedDateTime = Temporal.Now.zonedDateTimeISO(); // 转换为Date对象会丢失纳秒精度,但日常展示场景完全足够 return temporalFormatter3.value.format(new Date(zonedDateTime.epochMilliseconds)); });
为什么单独调用ZonedDateTime没问题?
你单独调用Temporal.Now.zonedDateTimeISO()能正常输出,是因为这个方法本身返回的是一个合法的ZonedDateTime实例,只是Intl.DateTimeFormat的format方法目前还没适配这个类型的输入,所以传入后会触发运行时错误。
补充说明
随着Temporal API的普及,未来浏览器会逐步完善Intl API对它的原生支持,到时候可能就不需要这些转换步骤了。但就目前(2024年)的浏览器实现来看,上面的两种方案是最可靠的解决方式。
内容的提问来源于stack exchange,提问作者RhinoCan

