vremel
Version:
JavaScript date utility library for Temporal API
85 lines (78 loc) • 2.25 kB
text/typescript
import { isPlainDate, isZonedDateTime } from "../type-utils.js";
import type { Temporal } from "../types.js";
import { endOfTimeForZonedDateTime } from "./_endOfTimeForZonedDateTime.js";
export interface EndOfWeekOptions {
/**
* First day of the week.
* For example, in ISO calendar Monday is `1`, Sunday is `7`.
*/
firstDayOfWeek: number;
}
function endOfWeekWithDayPrecision(
dt: Temporal.PlainDate,
firstDayOfWeek: number,
): Temporal.PlainDate;
function endOfWeekWithDayPrecision(
dt: Temporal.PlainDateTime,
firstDayOfWeek: number,
): Temporal.PlainDateTime;
function endOfWeekWithDayPrecision(
dt: Temporal.PlainDate | Temporal.PlainDateTime,
firstDayOfWeek: number,
) {
return dt.add({
days: (firstDayOfWeek + dt.daysInWeek - dt.dayOfWeek - 1) % dt.daysInWeek,
});
}
/**
* Returns the end of a week for the given datetime.
* 'end of a week' is ambiguous and locale-dependent,
* so `firstDayOfWeek` option is required.
* This function supports a calendar with a fixed `daysInWeek`,
* even if the week contains more or less than 7 days.
* But it doesn't support a calendar which lacks a fixed number of days.
*
* @param dt datetime object which includes date info
* @returns Temporal object which represents the end of a week
*/
export function endOfWeek<
DateTime extends
| Temporal.PlainDate
| Temporal.PlainDateTime
| Temporal.ZonedDateTime,
>(dt: DateTime, options: EndOfWeekOptions): DateTime {
const firstDayOfWeek = options.firstDayOfWeek;
if (
!Number.isInteger(firstDayOfWeek) ||
firstDayOfWeek < 1 ||
firstDayOfWeek > dt.daysInWeek
) {
throw new Error(`${firstDayOfWeek} isn't a valid day of week`);
}
const timeArg = {
hour: 23,
minute: 59,
second: 59,
millisecond: 999,
microsecond: 999,
nanosecond: 999,
};
if (isZonedDateTime(dt)) {
const endOfWeek = endOfWeekWithDayPrecision(
dt.toPlainDate(),
firstDayOfWeek,
);
return endOfTimeForZonedDateTime(dt, {
year: endOfWeek.year,
month: endOfWeek.month,
day: endOfWeek.day,
...timeArg,
}) as DateTime;
}
if (isPlainDate(dt)) {
return endOfWeekWithDayPrecision(dt, firstDayOfWeek) as DateTime;
}
return endOfWeekWithDayPrecision(dt, firstDayOfWeek).with(
timeArg,
) as DateTime;
}