@internationalized/date
Advanced tools
Comparing version 3.0.0-nightly.3316 to 3.0.0-nightly-641446f65-240905
@@ -1,115 +0,1 @@ | ||
/** An interface that is compatible with any object with date fields. */ | ||
export interface AnyCalendarDate { | ||
readonly calendar: Calendar; | ||
readonly era: string; | ||
readonly year: number; | ||
readonly month: number; | ||
readonly day: number; | ||
copy(): this; | ||
} | ||
/** An interface that is compatible with any object with time fields. */ | ||
export interface AnyTime { | ||
readonly hour: number; | ||
readonly minute: number; | ||
readonly second: number; | ||
readonly millisecond: number; | ||
copy(): this; | ||
} | ||
/** An interface that is compatible with any object with both date and time fields. */ | ||
export interface AnyDateTime extends AnyCalendarDate, AnyTime { | ||
} | ||
/** | ||
* The Calendar interface represents a calendar system, including information | ||
* about how days, months, years, and eras are organized, and methods to perform | ||
* arithmetic on dates. | ||
*/ | ||
export interface Calendar { | ||
/** A string identifier for the calendar, as defined by Unicode CLDR. */ | ||
identifier: string; | ||
/** Creates a CalendarDate in this calendar from the given Julian day number. */ | ||
fromJulianDay(jd: number): CalendarDate; | ||
/** Converts a date in this calendar to a Julian day number. */ | ||
toJulianDay(date: AnyCalendarDate): number; | ||
/** Returns the number of days in the month of the given date. */ | ||
getDaysInMonth(date: AnyCalendarDate): number; | ||
/** Returns the number of months in the year of the given date. */ | ||
getMonthsInYear(date: AnyCalendarDate): number; | ||
/** Returns the number of years in the era of the given date. */ | ||
getYearsInEra(date: AnyCalendarDate): number; | ||
/** Returns a list of era identifiers for the calendar. */ | ||
getEras(): string[]; | ||
/** | ||
* Returns the minimum month number of the given date's year. | ||
* Normally, this is 1, but in some calendars such as the Japanese, | ||
* eras may begin in the middle of a year. | ||
*/ | ||
getMinimumMonthInYear?(date: AnyCalendarDate): number; | ||
/** | ||
* Returns the minimum day number of the given date's month. | ||
* Normally, this is 1, but in some calendars such as the Japanese, | ||
* eras may begin in the middle of a month. | ||
*/ | ||
getMinimumDayInMonth?(date: AnyCalendarDate): number; | ||
/** @private */ | ||
balanceDate?(date: AnyCalendarDate): void; | ||
/** @private */ | ||
balanceYearMonth?(date: AnyCalendarDate, previousDate: AnyCalendarDate): void; | ||
/** @private */ | ||
constrainDate?(date: AnyCalendarDate): void; | ||
/** @private */ | ||
isInverseEra?(date: AnyCalendarDate): boolean; | ||
} | ||
/** Represents an amount of time in calendar-specific units, for use when performing arithmetic. */ | ||
export interface DateDuration { | ||
/** The number of years to add or subtract. */ | ||
years?: number; | ||
/** The number of months to add or subtract. */ | ||
months?: number; | ||
/** The number of weeks to add or subtract. */ | ||
weeks?: number; | ||
/** The number of days to add or subtract. */ | ||
days?: number; | ||
} | ||
/** Represents an amount of time, for use whe performing arithmetic. */ | ||
export interface TimeDuration { | ||
/** The number of hours to add or subtract. */ | ||
hours?: number; | ||
/** The number of minutes to add or subtract. */ | ||
minutes?: number; | ||
/** The number of seconds to add or subtract. */ | ||
seconds?: number; | ||
/** The number of milliseconds to add or subtract. */ | ||
milliseconds?: number; | ||
} | ||
/** Represents an amount of time with both date and time components, for use when performing arithmetic. */ | ||
export interface DateTimeDuration extends DateDuration, TimeDuration { | ||
} | ||
export interface DateFields { | ||
era?: string; | ||
year?: number; | ||
month?: number; | ||
day?: number; | ||
} | ||
export interface TimeFields { | ||
hour?: number; | ||
minute?: number; | ||
second?: number; | ||
millisecond?: number; | ||
} | ||
export type DateField = keyof DateFields; | ||
export type TimeField = keyof TimeFields; | ||
export type Disambiguation = 'compatible' | 'earlier' | 'later' | 'reject'; | ||
export interface CycleOptions { | ||
/** Whether to round the field value to the nearest interval of the amount. */ | ||
round?: boolean; | ||
} | ||
export interface CycleTimeOptions extends CycleOptions { | ||
/** | ||
* Whether to use 12 or 24 hour time. If 12 hour time is chosen, the resulting value | ||
* will remain in the same day period as the original value (e.g. if the value is AM, | ||
* the resulting value also be AM). | ||
* @default 24 | ||
*/ | ||
hourCycle?: 12 | 24; | ||
} | ||
type Mutable<T> = { | ||
@@ -200,5 +86,5 @@ -readonly [P in keyof T]: T[P]; | ||
/** Returns the lesser of the two provider dates. */ | ||
export function minDate<A extends DateValue, B extends DateValue>(a: A, b: B): A | B; | ||
export function minDate<A extends DateValue, B extends DateValue>(a?: A | null, b?: B | null): A | B | null | undefined; | ||
/** Returns the greater of the two provider dates. */ | ||
export function maxDate<A extends DateValue, B extends DateValue>(a: A, b: B): A | B; | ||
export function maxDate<A extends DateValue, B extends DateValue>(a?: A | null, b?: B | null): A | B | null | undefined; | ||
/** Returns whether the given date is on a weekend in the given locale. */ | ||
@@ -208,2 +94,10 @@ export function isWeekend(date: DateValue, locale: string): boolean; | ||
export function isWeekday(date: DateValue, locale: string): boolean; | ||
/** | ||
* Takes a Unix epoch (milliseconds since 1970) and converts it to the provided time zone. | ||
*/ | ||
export function fromAbsolute(ms: number, timeZone: string): ZonedDateTime; | ||
/** | ||
* Takes a `Date` object and converts it to the provided time zone. | ||
*/ | ||
export function fromDate(date: Date, timeZone: string): ZonedDateTime; | ||
/** Converts a value with date components such as a `CalendarDateTime` or `ZonedDateTime` into a `CalendarDate`. */ | ||
@@ -252,2 +146,8 @@ export function toCalendarDate(dateTime: AnyCalendarDate): CalendarDate; | ||
export function parseAbsoluteToLocal(value: string): ZonedDateTime; | ||
/** | ||
* Parses an ISO 8601 duration string (e.g. "P3Y6M6W4DT12H30M5S"). | ||
* @param value An ISO 8601 duration string. | ||
* @returns A DateTimeDuration object. | ||
*/ | ||
export function parseDuration(value: string): Required<DateTimeDuration>; | ||
/** A CalendarDate represents a date without any time components in a specific calendar system. */ | ||
@@ -400,3 +300,3 @@ export class CalendarDate { | ||
readonly timeZone: string; | ||
/** The UTC offset for this time, in seconds. */ | ||
/** The UTC offset for this time, in milliseconds. */ | ||
readonly offset: number; | ||
@@ -429,3 +329,117 @@ constructor(year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number); | ||
} | ||
/** An interface that is compatible with any object with date fields. */ | ||
export interface AnyCalendarDate { | ||
readonly calendar: Calendar; | ||
readonly era: string; | ||
readonly year: number; | ||
readonly month: number; | ||
readonly day: number; | ||
copy(): this; | ||
} | ||
/** An interface that is compatible with any object with time fields. */ | ||
export interface AnyTime { | ||
readonly hour: number; | ||
readonly minute: number; | ||
readonly second: number; | ||
readonly millisecond: number; | ||
copy(): this; | ||
} | ||
/** An interface that is compatible with any object with both date and time fields. */ | ||
export interface AnyDateTime extends AnyCalendarDate, AnyTime { | ||
} | ||
/** | ||
* The Calendar interface represents a calendar system, including information | ||
* about how days, months, years, and eras are organized, and methods to perform | ||
* arithmetic on dates. | ||
*/ | ||
export interface Calendar { | ||
/** A string identifier for the calendar, as defined by Unicode CLDR. */ | ||
identifier: string; | ||
/** Creates a CalendarDate in this calendar from the given Julian day number. */ | ||
fromJulianDay(jd: number): CalendarDate; | ||
/** Converts a date in this calendar to a Julian day number. */ | ||
toJulianDay(date: AnyCalendarDate): number; | ||
/** Returns the number of days in the month of the given date. */ | ||
getDaysInMonth(date: AnyCalendarDate): number; | ||
/** Returns the number of months in the year of the given date. */ | ||
getMonthsInYear(date: AnyCalendarDate): number; | ||
/** Returns the number of years in the era of the given date. */ | ||
getYearsInEra(date: AnyCalendarDate): number; | ||
/** Returns a list of era identifiers for the calendar. */ | ||
getEras(): string[]; | ||
/** | ||
* Returns the minimum month number of the given date's year. | ||
* Normally, this is 1, but in some calendars such as the Japanese, | ||
* eras may begin in the middle of a year. | ||
*/ | ||
getMinimumMonthInYear?(date: AnyCalendarDate): number; | ||
/** | ||
* Returns the minimum day number of the given date's month. | ||
* Normally, this is 1, but in some calendars such as the Japanese, | ||
* eras may begin in the middle of a month. | ||
*/ | ||
getMinimumDayInMonth?(date: AnyCalendarDate): number; | ||
/** @private */ | ||
balanceDate?(date: AnyCalendarDate): void; | ||
/** @private */ | ||
balanceYearMonth?(date: AnyCalendarDate, previousDate: AnyCalendarDate): void; | ||
/** @private */ | ||
constrainDate?(date: AnyCalendarDate): void; | ||
/** @private */ | ||
isInverseEra?(date: AnyCalendarDate): boolean; | ||
} | ||
/** Represents an amount of time in calendar-specific units, for use when performing arithmetic. */ | ||
export interface DateDuration { | ||
/** The number of years to add or subtract. */ | ||
years?: number; | ||
/** The number of months to add or subtract. */ | ||
months?: number; | ||
/** The number of weeks to add or subtract. */ | ||
weeks?: number; | ||
/** The number of days to add or subtract. */ | ||
days?: number; | ||
} | ||
/** Represents an amount of time, for use whe performing arithmetic. */ | ||
export interface TimeDuration { | ||
/** The number of hours to add or subtract. */ | ||
hours?: number; | ||
/** The number of minutes to add or subtract. */ | ||
minutes?: number; | ||
/** The number of seconds to add or subtract. */ | ||
seconds?: number; | ||
/** The number of milliseconds to add or subtract. */ | ||
milliseconds?: number; | ||
} | ||
/** Represents an amount of time with both date and time components, for use when performing arithmetic. */ | ||
export interface DateTimeDuration extends DateDuration, TimeDuration { | ||
} | ||
export interface DateFields { | ||
era?: string; | ||
year?: number; | ||
month?: number; | ||
day?: number; | ||
} | ||
export interface TimeFields { | ||
hour?: number; | ||
minute?: number; | ||
second?: number; | ||
millisecond?: number; | ||
} | ||
export type DateField = keyof DateFields; | ||
export type TimeField = keyof TimeFields; | ||
export type Disambiguation = 'compatible' | 'earlier' | 'later' | 'reject'; | ||
export interface CycleOptions { | ||
/** Whether to round the field value to the nearest interval of the amount. */ | ||
round?: boolean; | ||
} | ||
export interface CycleTimeOptions extends CycleOptions { | ||
/** | ||
* Whether to use 12 or 24 hour time. If 12 hour time is chosen, the resulting value | ||
* will remain in the same day period as the original value (e.g. if the value is AM, | ||
* the resulting value also be AM). | ||
* @default 24 | ||
*/ | ||
hourCycle?: 12 | 24; | ||
} | ||
/** | ||
* The Japanese calendar is based on the Gregorian calendar, but with eras for the reign of each Japanese emperor. | ||
@@ -432,0 +446,0 @@ * Whenever a new emperor ascends to the throne, a new era begins and the year starts again from 1. |
{ | ||
"name": "@internationalized/date", | ||
"version": "3.0.0-nightly.3316+73ade2986", | ||
"version": "3.0.0-nightly-641446f65-240905", | ||
"description": "Internationalized calendar, date, and time manipulation utilities", | ||
@@ -8,2 +8,7 @@ "license": "Apache-2.0", | ||
"module": "dist/module.js", | ||
"exports": { | ||
"types": "./dist/types.d.ts", | ||
"import": "./dist/import.mjs", | ||
"require": "./dist/main.js" | ||
}, | ||
"types": "dist/types.d.ts", | ||
@@ -21,3 +26,3 @@ "source": "src/index.ts", | ||
"dependencies": { | ||
"@babel/runtime": "^7.6.2" | ||
"@swc/helpers": "^0.5.0" | ||
}, | ||
@@ -27,3 +32,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "73ade29862f171cd6c37337ae76a880d6f598d32" | ||
} | ||
"stableVersion": "3.5.5" | ||
} |
@@ -12,3 +12,3 @@ # @internationalized/date | ||
* **Queries** – Compare dates and times for ordering or full/partial equality. Determine locale-specific metadata such as day of week, weekend/weekday, etc. | ||
* **Time zone aware** – The [ZonedDateTime](https://react-specrum.adobe.com/internationalized/date/ZonedDateTime.html) object supports time zone aware date and time manipulation. | ||
* **Time zone aware** – The [ZonedDateTime](https://react-spectrum.adobe.com/internationalized/date/ZonedDateTime.html) object supports time zone aware date and time manipulation. | ||
* **Predictable** – The API is designed to resolve ambiguity in all operations explicitly, including time zone conversions, arithmetic involving daylight saving time, locale-specific queries, and more. | ||
@@ -28,7 +28,7 @@ * **Small bundle size** – The entire library including all calendars and functions is 8 kB minified and compressed with Brotli. | ||
* [Calendar](https://react-specrum.adobe.com/internationalized/date/Calendar.html) – An interface which provides calendar conversion and metadata like number of days in month, and number of months in year. Many implementations are provided to support the most commonly used calendar systems. | ||
* [CalendarDate](https://react-specrum.adobe.com/internationalized/date/CalendarDate.html) – An immutable object that stores a date associated with a specific calendar system, without any time components. | ||
* [CalendarDateTime](https://react-specrum.adobe.com/internationalized/date/CalendarDateTime.html) – An immutable object that represents a date and time without a time zone, in a specific calendar system. | ||
* [ZonedDateTime](https://react-specrum.adobe.com/internationalized/date/ZonedDateTime.html) – An immutable object that represents a date and time in a specific time zone and calendar system. | ||
* [Time](https://react-specrum.adobe.com/internationalized/date/Time.html) – An immutable object that stores a clock time without any date components. | ||
* [Calendar](https://react-spectrum.adobe.com/internationalized/date/Calendar.html) – An interface which provides calendar conversion and metadata like number of days in month, and number of months in year. Many implementations are provided to support the most commonly used calendar systems. | ||
* [CalendarDate](https://react-spectrum.adobe.com/internationalized/date/CalendarDate.html) – An immutable object that stores a date associated with a specific calendar system, without any time components. | ||
* [CalendarDateTime](https://react-spectrum.adobe.com/internationalized/date/CalendarDateTime.html) – An immutable object that represents a date and time without a time zone, in a specific calendar system. | ||
* [ZonedDateTime](https://react-spectrum.adobe.com/internationalized/date/ZonedDateTime.html) – An immutable object that represents a date and time in a specific time zone and calendar system. | ||
* [Time](https://react-spectrum.adobe.com/internationalized/date/Time.html) – An immutable object that stores a clock time without any date components. | ||
@@ -35,0 +35,0 @@ Each object includes methods to allow basic manipulation and conversion functionality, such as adding and subtracting durations, and formatting as an ISO 8601 string. Additional less commonly used functions can be imported from the `@internationalized/date` package, and passed a date object as a parameter. This includes functions to parse ISO 8601 strings, query properties such as day of week, convert between time zones and much more. See the documentation for each of the objects to learn more about the supported methods and functions. |
@@ -45,2 +45,3 @@ /* | ||
// If that behavior is desired, use the AnyCalendarDate interface instead. | ||
// @ts-ignore | ||
#type; | ||
@@ -128,2 +129,3 @@ /** The calendar system associated with this date, e.g. Gregorian. */ | ||
// This prevents TypeScript from allowing other types with the same fields to match. | ||
// @ts-ignore | ||
#type; | ||
@@ -194,2 +196,3 @@ /** The hour, numbered from 0 to 23. */ | ||
// This prevents TypeScript from allowing other types with the same fields to match. | ||
// @ts-ignore | ||
#type; | ||
@@ -302,2 +305,3 @@ /** The calendar system associated with this date, e.g. Gregorian. */ | ||
// This prevents TypeScript from allowing other types with the same fields to match. | ||
// @ts-ignore | ||
#type; | ||
@@ -328,3 +332,3 @@ /** The calendar system associated with this date, e.g. Gregorian. */ | ||
public readonly timeZone: string; | ||
/** The UTC offset for this time, in seconds. */ | ||
/** The UTC offset for this time, in milliseconds. */ | ||
public readonly offset: number; | ||
@@ -331,0 +335,0 @@ |
@@ -20,27 +20,20 @@ /* | ||
const PERSIAN_EPOCH = 1948321; // 622/03/19 Julian C.E. | ||
const PERSIAN_EPOCH = 1948320; | ||
function isLeapYear(year: number): boolean { | ||
let y0 = year > 0 ? year - 474 : year - 473; | ||
let y1 = mod(y0, 2820) + 474; | ||
// Number of days from the start of the year to the start of each month. | ||
const MONTH_START = [ | ||
0, // Farvardin | ||
31, // Ordibehesht | ||
62, // Khordad | ||
93, // Tir | ||
124, // Mordad | ||
155, // Shahrivar | ||
186, // Mehr | ||
216, // Aban | ||
246, // Azar | ||
276, // Dey | ||
306, // Bahman | ||
336 // Esfand | ||
]; | ||
return mod((y1 + 38) * 31, 128) < 31; | ||
} | ||
function persianToJulianDay(year: number, month: number, day: number): number { | ||
let y0 = year > 0 ? year - 474 : year - 473; | ||
let y1 = mod(y0, 2820) + 474; | ||
let offset = month <= 7 ? 31 * (month - 1) : 30 * (month - 1) + 6; | ||
return ( | ||
PERSIAN_EPOCH - | ||
1 + | ||
1029983 * Math.floor(y0 / 2820) + | ||
365 * (y1 - 1) + | ||
Math.floor((31 * y1 - 5) / 128) + | ||
offset + | ||
day | ||
); | ||
} | ||
/** | ||
@@ -56,20 +49,18 @@ * The Persian calendar is the main calendar used in Iran and Afghanistan. It has 12 months | ||
fromJulianDay(jd: number): CalendarDate { | ||
let d0 = jd - persianToJulianDay(475, 1, 1); | ||
let n2820 = Math.floor(d0 / 1029983); | ||
let d1 = mod(d0, 1029983); | ||
let y2820 = d1 === 1029982 ? 2820 : Math.floor((128 * d1 + 46878) / 46751); | ||
let year = 474 + 2820 * n2820 + y2820; | ||
if (year <= 0) { | ||
year--; | ||
} | ||
let yDay = jd - persianToJulianDay(year, 1, 1) + 1; | ||
let month = yDay <= 186 ? Math.ceil(yDay / 31) : Math.ceil((yDay - 6) / 31); | ||
let day = jd - persianToJulianDay(year, month, 1) + 1; | ||
return new CalendarDate(this, year, month, day); | ||
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); | ||
let dayOfYear = daysSinceEpoch - farvardin1; | ||
let month = dayOfYear < 216 | ||
? Math.floor(dayOfYear / 31) | ||
: Math.floor((dayOfYear - 6) / 30); | ||
let day = dayOfYear - MONTH_START[month] + 1; | ||
return new CalendarDate(this, year, month + 1, day); | ||
} | ||
toJulianDay(date: AnyCalendarDate): number { | ||
return persianToJulianDay(date.year, date.month, date.day); | ||
let jd = PERSIAN_EPOCH - 1 + 365 * (date.year - 1) + Math.floor((8 * date.year + 21) / 33); | ||
jd += MONTH_START[date.month - 1]; | ||
jd += date.day; | ||
return jd; | ||
} | ||
@@ -90,3 +81,4 @@ | ||
return isLeapYear(date.year) ? 30 : 29; | ||
let isLeapYear = mod(25 * date.year + 11, 33) < 8; | ||
return isLeapYear ? 30 : 29; | ||
} | ||
@@ -93,0 +85,0 @@ |
@@ -44,4 +44,4 @@ /* | ||
// Fast path: for local timezone, use native Date. | ||
if (timeZone === getLocalTimeZone()) { | ||
// Fast path: for local timezone after 1970, use native Date. | ||
if (ms > 0 && timeZone === getLocalTimeZone()) { | ||
return new Date(ms).getTimezoneOffset() * -60 * 1000; | ||
@@ -177,2 +177,5 @@ } | ||
/** | ||
* Takes a Unix epoch (milliseconds since 1970) and converts it to the provided time zone. | ||
*/ | ||
export function fromAbsolute(ms: number, timeZone: string): ZonedDateTime { | ||
@@ -192,2 +195,5 @@ let offset = getTimeZoneOffset(ms, timeZone); | ||
/** | ||
* Takes a `Date` object and converts it to the provided time zone. | ||
*/ | ||
export function fromDate(date: Date, timeZone: string): ZonedDateTime { | ||
@@ -194,0 +200,0 @@ return fromAbsolute(date.getTime(), timeZone); |
@@ -136,3 +136,3 @@ /* | ||
if (formatterCache.has(cacheKey)) { | ||
return formatterCache.get(cacheKey); | ||
return formatterCache.get(cacheKey)!; | ||
} | ||
@@ -145,3 +145,3 @@ | ||
let _hasBuggyHour12Behavior: boolean = null; | ||
let _hasBuggyHour12Behavior: boolean | null = null; | ||
function hasBuggyHour12Behavior() { | ||
@@ -158,3 +158,3 @@ if (_hasBuggyHour12Behavior == null) { | ||
let _hasBuggyResolvedHourCycle: boolean = null; | ||
let _hasBuggyResolvedHourCycle: boolean | null = null; | ||
function hasBuggyResolvedHourCycle() { | ||
@@ -185,4 +185,4 @@ if (_hasBuggyResolvedHourCycle == null) { | ||
let min = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 0)).find(p => p.type === 'hour').value, 10); | ||
let max = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 23)).find(p => p.type === 'hour').value, 10); | ||
let min = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 0)).find(p => p.type === 'hour')!.value, 10); | ||
let max = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 23)).find(p => p.type === 'hour')!.value, 10); | ||
@@ -189,0 +189,0 @@ if (min === 0 && max === 23) { |
@@ -13,2 +13,19 @@ /* | ||
export type { | ||
AnyCalendarDate, | ||
AnyTime, | ||
AnyDateTime, | ||
Calendar, | ||
DateDuration, | ||
TimeDuration, | ||
DateTimeDuration, | ||
DateFields, | ||
TimeFields, | ||
DateField, | ||
TimeField, | ||
Disambiguation, | ||
CycleOptions, | ||
CycleTimeOptions | ||
} from './types'; | ||
export {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from './CalendarDate'; | ||
@@ -25,4 +42,14 @@ export {GregorianCalendar} from './calendars/GregorianCalendar'; | ||
export {createCalendar} from './createCalendar'; | ||
export {toCalendarDate, toCalendarDateTime, toTime, toCalendar, toZoned, toTimeZone, toLocalTimeZone} from './conversion'; | ||
export { | ||
toCalendarDate, | ||
toCalendarDateTime, | ||
toTime, | ||
toCalendar, | ||
toZoned, | ||
toTimeZone, | ||
toLocalTimeZone, | ||
fromDate, | ||
fromAbsolute | ||
} from './conversion'; | ||
export { | ||
isSameDay, | ||
@@ -54,3 +81,2 @@ isSameMonth, | ||
} from './queries'; | ||
export * from './types'; | ||
export { | ||
@@ -62,4 +88,5 @@ parseDate, | ||
parseAbsoluteToLocal, | ||
parseZonedDateTime | ||
parseZonedDateTime, | ||
parseDuration | ||
} from './string'; | ||
export {DateFormatter} from './DateFormatter'; |
@@ -13,3 +13,3 @@ /* | ||
import {AnyCalendarDate, AnyTime, CycleOptions, CycleTimeOptions, DateDuration, DateField, DateFields, DateTimeDuration, Disambiguation, TimeDuration, TimeField, TimeFields} from './types'; | ||
import {AnyCalendarDate, AnyDateTime, AnyTime, CycleOptions, CycleTimeOptions, DateDuration, DateField, DateFields, DateTimeDuration, Disambiguation, TimeDuration, TimeField, TimeFields} from './types'; | ||
import {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from './CalendarDate'; | ||
@@ -26,4 +26,4 @@ import {epochFromDate, fromAbsolute, toAbsolute, toCalendar, toCalendarDateTime} from './conversion'; | ||
export function add(date: CalendarDate | CalendarDateTime, duration: DateTimeDuration) { | ||
let mutableDate: Mutable<AnyCalendarDate> = date.copy(); | ||
let days = 'hour' in date ? addTimeFields(date, duration) : 0; | ||
let mutableDate: Mutable<AnyCalendarDate | AnyDateTime> = date.copy(); | ||
let days = 'hour' in mutableDate ? addTimeFields(mutableDate, duration) : 0; | ||
@@ -369,6 +369,7 @@ addYears(mutableDate, duration.years || 0); | ||
let ms: number; | ||
if ((duration.years != null && duration.years !== 0) || (duration.months != null && duration.months !== 0) || (duration.days != null && duration.days !== 0)) { | ||
if ((duration.years != null && duration.years !== 0) || (duration.months != null && duration.months !== 0) || (duration.weeks != null && duration.weeks !== 0) || (duration.days != null && duration.days !== 0)) { | ||
let res = add(toCalendarDateTime(dateTime), { | ||
years: duration.years, | ||
months: duration.months, | ||
weeks: duration.weeks, | ||
days: duration.days | ||
@@ -427,3 +428,3 @@ }); | ||
let maxAbsolute = [toAbsolute(maxDate, dateTime.timeZone, 'earlier'), toAbsolute(maxDate, dateTime.timeZone, 'later')] | ||
.filter(ms => fromAbsolute(ms, dateTime.timeZone).day === maxDate.day).pop(); | ||
.filter(ms => fromAbsolute(ms, dateTime.timeZone).day === maxDate.day).pop()!; | ||
@@ -430,0 +431,0 @@ // Since hours may repeat, we need to operate on the absolute time in milliseconds. |
@@ -118,3 +118,3 @@ /* | ||
let localTimeZone = null; | ||
let localTimeZone: string | null = null; | ||
@@ -128,3 +128,3 @@ /** Returns the time zone identifier for the current user. */ | ||
return localTimeZone; | ||
return localTimeZone!; | ||
} | ||
@@ -205,3 +205,3 @@ | ||
function getRegion(locale: string) { | ||
function getRegion(locale: string): string | undefined { | ||
// If the Intl.Locale API is available, use it to get the region for the locale. | ||
@@ -215,3 +215,5 @@ // @ts-ignore | ||
region = new Intl.Locale(locale).maximize().region; | ||
cachedRegions.set(locale, region); | ||
if (region) { | ||
cachedRegions.set(locale, region); | ||
} | ||
} | ||
@@ -226,10 +228,10 @@ return region; | ||
let part = locale.split('-')[1]; | ||
return part === 'u' ? null : part; | ||
return part === 'u' ? undefined : part; | ||
} | ||
function getWeekStart(locale: string) { | ||
function getWeekStart(locale: string): number { | ||
// TODO: use Intl.Locale for this once browsers support the weekInfo property | ||
// https://github.com/tc39/proposal-intl-locale-info | ||
let region = getRegion(locale); | ||
return weekStartData[region] || 0; | ||
return region ? weekStartData[region] || 0 : 0; | ||
} | ||
@@ -244,3 +246,3 @@ | ||
/** Returns the lesser of the two provider dates. */ | ||
export function minDate<A extends DateValue, B extends DateValue>(a: A, b: B): A | B { | ||
export function minDate<A extends DateValue, B extends DateValue>(a?: A | null, b?: B | null): A | B | null | undefined { | ||
if (a && b) { | ||
@@ -254,3 +256,3 @@ return a.compare(b) <= 0 ? a : b; | ||
/** Returns the greater of the two provider dates. */ | ||
export function maxDate<A extends DateValue, B extends DateValue>(a: A, b: B): A | B { | ||
export function maxDate<A extends DateValue, B extends DateValue>(a?: A | null, b?: B | null): A | B | null | undefined { | ||
if (a && b) { | ||
@@ -297,3 +299,3 @@ return a.compare(b) >= 0 ? a : b; | ||
// https://github.com/tc39/proposal-intl-locale-info | ||
let [start, end] = WEEKEND_DATA[region] || [6, 0]; | ||
let [start, end] = WEEKEND_DATA[region!] || [6, 0]; | ||
return dayOfWeek === start || dayOfWeek === end; | ||
@@ -300,0 +302,0 @@ } |
@@ -13,3 +13,3 @@ /* | ||
import {AnyDateTime, Disambiguation} from './types'; | ||
import {AnyDateTime, DateTimeDuration, Disambiguation} from './types'; | ||
import {CalendarDate, CalendarDateTime, Time, ZonedDateTime} from './CalendarDate'; | ||
@@ -24,4 +24,8 @@ import {epochFromDate, fromAbsolute, possibleAbsolutes, toAbsolute, toCalendar, toCalendarDateTime, toTimeZone} from './conversion'; | ||
const DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?$/; | ||
const ZONED_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:([+-]\d{2})(?::(\d{2}))?)?\[(.*?)\]$/; | ||
const ABSOLUTE_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:(?:([+-]\d{2})(?::(\d{2}))?)|Z)$/; | ||
const ZONED_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:([+-]\d{2})(?::?(\d{2}))?)?\[(.*?)\]$/; | ||
const ABSOLUTE_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:(?:([+-]\d{2})(?::?(\d{2}))?)|Z)$/; | ||
const DATE_TIME_DURATION_RE = | ||
/^((?<negative>-)|\+)?P((?<years>\d*)Y)?((?<months>\d*)M)?((?<weeks>\d*)W)?((?<days>\d*)D)?((?<time>T)((?<hours>\d*[.,]?\d{1,9})H)?((?<minutes>\d*[.,]?\d{1,9})M)?((?<seconds>\d*[.,]?\d{1,9})S)?)?$/; | ||
const requiredDurationTimeGroups = ['hours', 'minutes', 'seconds']; | ||
const requiredDurationGroups = ['years', 'months', 'weeks', 'days', ...requiredDurationTimeGroups]; | ||
@@ -200,1 +204,68 @@ /** Parses an ISO 8601 time string. */ | ||
} | ||
/** | ||
* Parses an ISO 8601 duration string (e.g. "P3Y6M6W4DT12H30M5S"). | ||
* @param value An ISO 8601 duration string. | ||
* @returns A DateTimeDuration object. | ||
*/ | ||
export function parseDuration(value: string): Required<DateTimeDuration> { | ||
const match = value.match(DATE_TIME_DURATION_RE); | ||
if (!match) { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value}`); | ||
} | ||
const parseDurationGroup = ( | ||
group: string | undefined, | ||
isNegative: boolean, | ||
min: number, | ||
max: number | ||
): number => { | ||
if (!group) { | ||
return 0; | ||
} | ||
try { | ||
const sign = isNegative ? -1 : 1; | ||
return sign * parseNumber(group.replace(',', '.'), min, max); | ||
} catch { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value}`); | ||
} | ||
}; | ||
const isNegative = !!match.groups?.negative; | ||
const hasRequiredGroups = requiredDurationGroups.some(group => match.groups?.[group]); | ||
if (!hasRequiredGroups) { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value}`); | ||
} | ||
const durationStringIncludesTime = match.groups?.time; | ||
if (durationStringIncludesTime) { | ||
const hasRequiredDurationTimeGroups = requiredDurationTimeGroups.some(group => match.groups?.[group]); | ||
if (!hasRequiredDurationTimeGroups) { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value}`); | ||
} | ||
} | ||
const duration: Mutable<DateTimeDuration> = { | ||
years: parseDurationGroup(match.groups?.years, isNegative, 0, 9999), | ||
months: parseDurationGroup(match.groups?.months, isNegative, 0, 12), | ||
weeks: parseDurationGroup(match.groups?.weeks, isNegative, 0, Infinity), | ||
days: parseDurationGroup(match.groups?.days, isNegative, 0, 31), | ||
hours: parseDurationGroup(match.groups?.hours, isNegative, 0, 23), | ||
minutes: parseDurationGroup(match.groups?.minutes, isNegative, 0, 59), | ||
seconds: parseDurationGroup(match.groups?.seconds, isNegative, 0, 59) | ||
}; | ||
if (duration.hours !== undefined && ((duration.hours % 1) !== 0) && (duration.minutes || duration.seconds)) { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value} - only the smallest unit can be fractional`); | ||
} | ||
if (duration.minutes !== undefined && ((duration.minutes % 1) !== 0) && duration.seconds) { | ||
throw new Error(`Invalid ISO 8601 Duration string: ${value} - only the smallest unit can be fractional`); | ||
} | ||
return duration as Required<DateTimeDuration>; | ||
} |
@@ -24,3 +24,5 @@ /* | ||
AN: 1, | ||
AR: 1, | ||
AT: 1, | ||
AU: 1, | ||
AX: 1, | ||
@@ -38,2 +40,3 @@ AZ: 1, | ||
CM: 1, | ||
CN: 1, | ||
CR: 1, | ||
@@ -40,0 +43,0 @@ CY: 1, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 10 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
985114
119
11849
10
60
+ Added@swc/helpers@^0.5.0
+ Added@swc/helpers@0.5.15(transitive)
+ Addedtslib@2.8.1(transitive)
- Removed@babel/runtime@^7.6.2
- Removed@babel/runtime@7.26.0(transitive)
- Removedregenerator-runtime@0.14.1(transitive)