Skip to content

Commit

Permalink
Refactor CalendarDate to return AnyCalendarDate type
Browse files Browse the repository at this point in the history
  • Loading branch information
1amageek committed Nov 26, 2024
1 parent 6eaf379 commit 6f4a9b7
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 79 deletions.
16 changes: 5 additions & 11 deletions packages/@internationalized/date/src/CalendarDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ function shiftArgs(args: any[]) {
/** A CalendarDate represents a date without any time components in a specific calendar system. */
export class CalendarDate {
// This prevents TypeScript from allowing other types with the same fields to match.
// i.e. a ZonedDateTime should not be be passable to a parameter that expects CalendarDate.
// If that behavior is desired, use the AnyCalendarDate interface instead.
// @ts-ignore
#type;
/** The calendar system associated with this date, e.g. Gregorian. */
Expand Down Expand Up @@ -76,13 +74,11 @@ export class CalendarDate {
second: 0,
millisecond: 0
});

this.calendar = calendar;
this.calendar = normalized.calendar;
this.era = normalized.era;
this.year = normalized.year;
this.month = normalized.month;
this.day = normalized.day;

constrain(this);
}

Expand Down Expand Up @@ -251,7 +247,7 @@ export class CalendarDateTime {
millisecond
});

this.calendar = calendar;
this.calendar = normalized.calendar;
this.era = normalized.era;
this.year = normalized.year;
this.month = normalized.month;
Expand All @@ -260,7 +256,6 @@ export class CalendarDateTime {
this.minute = normalized.minute;
this.second = normalized.second;
this.millisecond = normalized.millisecond;

constrain(this);
}

Expand Down Expand Up @@ -372,7 +367,7 @@ export class ZonedDateTime {

const normalized = normalize({
calendar,
era: era,
era,
year,
month,
day,
Expand All @@ -382,8 +377,8 @@ export class ZonedDateTime {
millisecond
});

this.calendar = calendar;
this.era = era;
this.calendar = normalized.calendar;
this.era = normalized.era;
this.year = normalized.year;
this.month = normalized.month;
this.day = normalized.day;
Expand All @@ -393,7 +388,6 @@ export class ZonedDateTime {
this.minute = normalized.minute;
this.second = normalized.second;
this.millisecond = normalized.millisecond;

constrain(this);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ const BUDDHIST_ERA_START = -543;
export class BuddhistCalendar extends GregorianCalendar {
identifier = 'buddhist';

fromJulianDay(jd: number): CalendarDate {
fromJulianDay(jd: number): AnyCalendarDate {
let gregorianDate = super.fromJulianDay(jd);
let year = getExtendedYear(gregorianDate.era, gregorianDate.year);
return new CalendarDate(
this,
year - BUDDHIST_ERA_START,
gregorianDate.month,
gregorianDate.day
);

return {
calendar: this,
era: 'BE', // Buddhist Era
year: year - BUDDHIST_ERA_START,
month: gregorianDate.month,
day: gregorianDate.day
};
}

toJulianDay(date: AnyCalendarDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// Original licensing can be found in the NOTICE file in the root directory of this source tree.

import {AnyCalendarDate, Calendar} from '../types';
import {CalendarDate} from '../CalendarDate';
import {mod, Mutable} from '../utils';

const EPOCH = 1721426; // 001/01/03 Julian C.E.
Expand Down Expand Up @@ -70,7 +69,7 @@ const daysInMonth = {
export class GregorianCalendar implements Calendar {
identifier = 'gregory';

fromJulianDay(jd: number): CalendarDate {
fromJulianDay(jd: number): AnyCalendarDate {
let jd0 = jd;
let depoch = jd0 - EPOCH;
let quadricent = Math.floor(depoch / 146097);
Expand All @@ -93,7 +92,13 @@ export class GregorianCalendar implements Calendar {
let month = Math.floor(((yearDay + leapAdj) * 12 + 373) / 367);
let day = jd0 - gregorianToJulianDay(era, year, month, 1) + 1;

return new CalendarDate(era, year, month, day);
return {
calendar: this,
era,
year,
month,
day
};
}

toJulianDay(date: AnyCalendarDate): number {
Expand Down
14 changes: 10 additions & 4 deletions packages/@internationalized/date/src/calendars/IndianCalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// Original licensing can be found in the NOTICE file in the root directory of this source tree.

import {AnyCalendarDate} from '../types';
import {CalendarDate} from '../CalendarDate';
import {fromExtendedYear, GregorianCalendar, gregorianToJulianDay, isLeapYear} from './GregorianCalendar';

// Starts in 78 AD,
Expand All @@ -31,7 +30,7 @@ const INDIAN_YEAR_START = 80;
export class IndianCalendar extends GregorianCalendar {
identifier = 'indian';

fromJulianDay(jd: number): CalendarDate {
fromJulianDay(jd: number): AnyCalendarDate {
// Gregorian date for Julian day
let date = super.fromJulianDay(jd);

Expand Down Expand Up @@ -71,8 +70,15 @@ export class IndianCalendar extends GregorianCalendar {
indianDay = (mDay % 30) + 1;
}
}

return new CalendarDate(this, indianYear, indianMonth, indianDay);
const eras = this.getEras();
const era = eras[eras.length - 1];
return {
calendar: this,
era: era,
year: indianYear,
month: indianMonth,
day: indianDay
};
}

toJulianDay(date: AnyCalendarDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,13 @@ function toGregorian(date: AnyCalendarDate) {
throw new Error('Unknown era: ' + date.era);
}

return new CalendarDate(
date.year + eraAddend,
date.month,
date.day
);
return {
era: 'AD',
year: date.year + eraAddend,
month: date.month,
day: date.day,
calendar: new GregorianCalendar()
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// Original licensing can be found in the NOTICE file in the root directory of this source tree.

import {AnyCalendarDate, Calendar} from '../types';
import {CalendarDate} from '../CalendarDate';
import {mod} from '../utils';

const PERSIAN_EPOCH = 1948320;
Expand Down Expand Up @@ -44,7 +43,7 @@ const MONTH_START = [
export class PersianCalendar implements Calendar {
identifier = 'persian';

fromJulianDay(jd: number): CalendarDate {
fromJulianDay(jd: number): AnyCalendarDate {
let daysSinceEpoch = jd - PERSIAN_EPOCH;
let year = 1 + Math.floor((33 * daysSinceEpoch + 3) / 12053);
let farvardin1 = 365 * (year - 1) + Math.floor((8 * year + 21) / 33);
Expand All @@ -53,7 +52,14 @@ export class PersianCalendar implements Calendar {
? Math.floor(dayOfYear / 31)
: Math.floor((dayOfYear - 6) / 30);
let day = dayOfYear - MONTH_START[month] + 1;
return new CalendarDate(this, year, month + 1, day);

return {
calendar: this,
era: 'AP', // Anno Persico/Persian Era
year,
month: month + 1,
day
};
}

toJulianDay(date: AnyCalendarDate): number {
Expand Down
13 changes: 7 additions & 6 deletions packages/@internationalized/date/src/calendars/TaiwanCalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ export class TaiwanCalendar extends GregorianCalendar {

function toGregorian(date: AnyCalendarDate) {
let [era, year] = fromExtendedYear(gregorianYear(date));
return new CalendarDate(
era,
year,
date.month,
date.day
);
return {
era: era,
year: year,
month: date.month,
day: date.day,
calendar: new GregorianCalendar()
};
}
6 changes: 3 additions & 3 deletions packages/@internationalized/date/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
// Portions of the code in this file are based on code from the TC39 Temporal proposal.
// Original licensing can be found in the NOTICE file in the root directory of this source tree.

import {AnyCalendarDate, AnyDateTime, AnyTime, Calendar, DateFields, Disambiguation, TimeFields} from './types';
import {AnyCalendarDate, AnyDateTime, AnyTime, Calendar, Copyable, DateFields, Disambiguation, TimeFields} from './types';
import {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from './CalendarDate';
import {constrain} from './manipulation';
import {getExtendedYear, GregorianCalendar} from './calendars/GregorianCalendar';
import {getLocalTimeZone} from './queries';
import {Mutable} from './utils';

export function epochFromDate(date: AnyDateTime) {
export function epochFromDate(date: AnyDateTime & Copyable) {
date = toCalendar(date, new GregorianCalendar());
let year = getExtendedYear(date.era, date.year);
return epochFromParts(year, date.month, date.day, date.hour, date.minute, date.second, date.millisecond);
Expand Down Expand Up @@ -259,7 +259,7 @@ export function toTime(dateTime: CalendarDateTime | ZonedDateTime): Time {
}

/** Converts a date from one calendar system to another. */
export function toCalendar<T extends AnyCalendarDate>(date: T, calendar: Calendar): T {
export function toCalendar<T extends AnyCalendarDate & Copyable>(date: T, calendar: Calendar): T {
if (date.calendar.identifier === calendar.identifier) {
return date;
}
Expand Down
Loading

0 comments on commit 6f4a9b7

Please sign in to comment.