如何使用 'Temporal' API 在不同的日历日期之间进行转换

How to use 'Temporal' API to Convert between Different Calendar Dates

使用 Temporal.Calendar of the upcoming proposal of the Temporal 全局对象,以下短函数在日历日期(Javascript 中识别的 18 个日历)之间进行转换。

目前,Temporal.Calendar 为其他日历返回的输出日期格式为(示例):'2022-02-25[u-ca=persian]'

如何避免使用toString().split("[")[0])获取不带后缀[u-ca=CalendarName]的日历日期,因为Intl.DateTimeFormat()无法识别后缀?

<script type='module'>
// ====== load Temporray polyfill (not needed after full Temporal implementation) ========
import * as TemporalModule from 'https://cdn.jsdelivr.net/npm/@js-temporal/polyfill@0.3.0/dist/index.umd.js'
//=====================================================================

// Y,M,D are the date to convert from
// options as in Intl.DateTimeFormat() with additional 'from' and 'locale'
// 'from': calendar name to convert from
// 'locale' the locale to use (default 'en')
// 'calendar': calendar to convert to
// All other options as in Intl.DateTimeFormat()
//---------------------------------------
function dateToCalendars(Y, M, D, op={}) {
return new Intl.DateTimeFormat(op.locale??="en",op).format(new Date(temporal.Temporal.PlainDateTime.from({year:Y,month:M,day:D,calendar:op.from??= "gregory"}).toString().split("[")[0]));
}
//---------------------------------------

//===============================
// Example Test Cases
//===============================

console.log(dateToCalendars(2022,2,25));     // default Gregory

// full format Gregory
console.log(dateToCalendars(2022,2,25, {dateStyle: "full"}));    

// from Persian to Gregory in full format
console.log(dateToCalendars(1400,12,6,{from: 'persian', dateStyle: "full"})); 

// from Persian to Gregory in full format in 'fa' locale
console.log(dateToCalendars(1400,12,6,{from: 'persian', dateStyle: "full", locale: "fa"}));

// from Persian to Islamic in full format in 'fa' locale
console.log(dateToCalendars(1400,12,6,{from: 'persian', calendar: 'islamic', dateStyle:"full", locale: "fa"})); 

// from Islamic to Gregory full format (default 'en' locale)
console.log(dateToCalendars(1443,7,24,{from:"islamic", dateStyle:"full"}));  

// from Hebrew to Islamic in full format
console.log(dateToCalendars(5782,6,24,{from: 'hebrew', calendar:"islamic", dateStyle:"full"}));  

// from Hebrew to Islamic in full format in 'ar' locale
console.log(dateToCalendars(5782,6,24,{from: 'hebrew', calendar:"islamic", dateStyle:"full", locale: 'ar'}));  

// from Hebrew to Persian in full format
console.log(dateToCalendars(5782,6,24,{from: 'hebrew', calendar:"persian", dateStyle:"full"}));  

// from Hebrew to Gregory in full format in 'he' locale
console.log(dateToCalendars(5782,6,24,{from: 'hebrew', dateStyle:"full", locale: 'he'})); 

</script> 

您可以将 Temporal.PlainDateTime 对象直接传递给 Intl.DateTimeFormat,或使用 Temporal.Calendar.prototype.toLocaleString() 间接传递。这应该使您不必拆分字符串以删除括号。

(一个好的经验法则是,如果您发现自己使用任何 Temporal 对象的 toString() 的输出进行字符串操作,或者就此使用 new Date(),这可能表明存在您应该改用时间方法。)

需要注意的是,您必须确保区域设置的日历与您正在设置格式的日期的日历相匹配。您不能使用 toLocaleString() 或 Intl.DateTimeFormat 进行日历转换(除非它来自 ISO 8601 日历)。 因此,您应该使用 withCalendar() 方法将日期转换为您想要输出的日历,并确保 Intl 选项中的日历与其匹配。

这是我对这样一个功能的尝试:

function dateToCalendars(year, month, day, op = {}) {
  const fromCalendar = op.from ?? 'gregory';
  const toCalendar = op.calendar ?? fromCalendar;
  const date = Temporal.PlainDate.from({ year, month, day, calendar: fromCalendar })
    .withCalendar(toCalendar);
  return date.toLocaleString(op.locale ?? 'en', { ...op, calendar: toCalendar });
}