UNPKG

@js-temporal/polyfill

Version:

Polyfill for Tc39 Stage 3 proposal Temporal (https://github.com/tc39/proposal-temporal)

141 lines (128 loc) 6.21 kB
import * as ES from './ecmascript'; import { MakeIntrinsicClass } from './intrinsicclass'; import { ISO_MONTH, ISO_DAY, ISO_YEAR, CALENDAR, GetSlot } from './slots'; import type { Temporal } from '..'; import { DateTimeFormat } from './intl'; import type { PlainMonthDayParams as Params, PlainMonthDayReturn as Return } from './internaltypes'; const ObjectCreate = Object.create; export class PlainMonthDay implements Temporal.PlainMonthDay { constructor( isoMonthParam: Params['constructor'][0], isoDayParam: Params['constructor'][0], calendarParam: Temporal.CalendarProtocol | string = ES.GetISO8601Calendar(), referenceISOYearParam = 1972 ) { const isoMonth = ES.ToIntegerThrowOnInfinity(isoMonthParam); const isoDay = ES.ToIntegerThrowOnInfinity(isoDayParam); const calendar = ES.ToTemporalCalendar(calendarParam); const referenceISOYear = ES.ToIntegerThrowOnInfinity(referenceISOYearParam); // Note: if the arguments are not passed, // ToIntegerThrowOnInfinity(undefined) will have returned 0, which will // be rejected by RejectISODate in CreateTemporalMonthDaySlots. This // check exists only to improve the error message. if (arguments.length < 2) { throw new RangeError('missing argument: isoMonth and isoDay are required'); } ES.CreateTemporalMonthDaySlots(this, isoMonth, isoDay, calendar, referenceISOYear); } get monthCode(): Return['monthCode'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this); } get day(): Return['day'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return ES.CalendarDay(GetSlot(this, CALENDAR), this); } get calendar(): Return['calendar'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return GetSlot(this, CALENDAR); } with(temporalMonthDayLike: Params['with'][0], optionsParam: Params['with'][1] = undefined): Return['with'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); if (!ES.IsObject(temporalMonthDayLike)) { throw new TypeError('invalid argument'); } ES.RejectObjectWithCalendarOrTimeZone(temporalMonthDayLike); const calendar = GetSlot(this, CALENDAR); const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year'] as const); const props = ES.PrepareTemporalFields(temporalMonthDayLike, fieldNames, 'partial'); if (!props) { throw new TypeError('invalid month-day-like'); } let fields = ES.PrepareTemporalFields(this, fieldNames, []); fields = ES.CalendarMergeFields(calendar, fields, props); fields = ES.PrepareTemporalFields(fields, fieldNames, []); const options = ES.GetOptionsObject(optionsParam); return ES.CalendarMonthDayFromFields(calendar, fields, options); } equals(otherParam: Params['equals'][0]): Return['equals'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); const other = ES.ToTemporalMonthDay(otherParam); for (const slot of [ISO_MONTH, ISO_DAY, ISO_YEAR]) { const val1 = GetSlot(this, slot); const val2 = GetSlot(other, slot); if (val1 !== val2) return false; } return ES.CalendarEquals(GetSlot(this, CALENDAR), GetSlot(other, CALENDAR)); } toString(optionsParam: Params['toString'][0] = undefined): string { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); const options = ES.GetOptionsObject(optionsParam); const showCalendar = ES.ToShowCalendarOption(options); return ES.TemporalMonthDayToString(this, showCalendar); } toJSON(): Return['toJSON'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return ES.TemporalMonthDayToString(this); } toLocaleString( locales: Params['toLocaleString'][0] = undefined, options: Params['toLocaleString'][1] = undefined ): string { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return new DateTimeFormat(locales, options).format(this); } valueOf(): never { throw new TypeError('use equals() to compare Temporal.PlainMonthDay'); } toPlainDate(item: Params['toPlainDate'][0]): Return['toPlainDate'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); if (!ES.IsObject(item)) throw new TypeError('argument should be an object'); const calendar = GetSlot(this, CALENDAR); const receiverFieldNames = ES.CalendarFields(calendar, ['day', 'monthCode'] as const); const fields = ES.PrepareTemporalFields(this, receiverFieldNames, []); const inputFieldNames = ES.CalendarFields(calendar, ['year'] as const); const inputFields = ES.PrepareTemporalFields(item, inputFieldNames, []); let mergedFields = ES.CalendarMergeFields(calendar, fields, inputFields); // TODO: Use MergeLists abstract operation. const mergedFieldNames = [...new Set([...receiverFieldNames, ...inputFieldNames])]; mergedFields = ES.PrepareTemporalFields(mergedFields, mergedFieldNames, []); const options = ObjectCreate(null); options.overflow = 'reject'; return ES.CalendarDateFromFields(calendar, mergedFields, options); } getISOFields(): Return['getISOFields'] { if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver'); return { calendar: GetSlot(this, CALENDAR), isoDay: GetSlot(this, ISO_DAY), isoMonth: GetSlot(this, ISO_MONTH), isoYear: GetSlot(this, ISO_YEAR) }; } static from(item: Params['from'][0], optionsParam: Params['from'][1] = undefined): Return['from'] { const options = ES.GetOptionsObject(optionsParam); if (ES.IsTemporalMonthDay(item)) { ES.ToTemporalOverflow(options); // validate and ignore return ES.CreateTemporalMonthDay( GetSlot(item, ISO_MONTH), GetSlot(item, ISO_DAY), GetSlot(item, CALENDAR), GetSlot(item, ISO_YEAR) ); } return ES.ToTemporalMonthDay(item, options); } [Symbol.toStringTag]!: 'Temporal.PlainMonthDay'; } MakeIntrinsicClass(PlainMonthDay, 'Temporal.PlainMonthDay');