Using the Temporal.Calendar of the upcoming proposal of the Temporal global Object, the following short function converts between calendar dates (the 18 Calendars recognized in Javascript).
Currently, the output date returned by Temporal.Calendar for other Calendars is in the format (example): '2022-02-25[u-ca=persian]'
How to avoid usingtoString().split("[")[0])
to get the calendar date without the suffix [u-ca=CalendarName]
as the Intl.DateTimeFormat()
does not recognize the suffix?
<script type='module'>
// ====== load Temporray polyfill (not needed after full Temporal implementation) ========
import * as TemporalModule from 'https://cdn.jsdelivr.net/npm/@js-temporal/[email protected]/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>
CodePudding user response:
You can pass the Temporal.PlainDateTime object directly to Intl.DateTimeFormat, or indirectly by using Temporal.Calendar.prototype.toLocaleString(). This should save you from having to split the string to remove the brackets.
(A good rule of thumb is that if you find yourself doing string manipulation with the output of toString() from any Temporal object, or using new Date()
for that matter, it's probably a sign that there's a Temporal method you should be using instead.)
One caveat is that you have to make sure that the calendar of the locale matches the calendar of the date you are formatting. You can't use toLocaleString() or Intl.DateTimeFormat to do calendar conversion (unless it is from the ISO 8601 calendar). So you should use the withCalendar() method to convert the date to the calendar you want to output it in, as well as making sure the calendar in the Intl options matches it.
Here's my attempt at such a function:
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 });
}