Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The `options` object has the following structure and defaults:
## Note about how zmanim are calculated
This library uses [Luxon](https://moment.github.io/luxon) as a date/time library, since
Javascript's `Date` object does not support setting timezones other than the system timezone.
All class methods that return a `DateTime` object will be in UTC.
All class methods that return a `Temporal.ZonedDateTime` object will be in UTC.

# Breaking changes from KosherJava
* `AstronomicalCalendar.getTemporalHour()` returns `null` instead of `Long.MIN_VALUE` if the calculations cannot be completed.
Expand Down
4,809 changes: 2,387 additions & 2,422 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
],
"dependencies": {
"big.js": "^6.1.1",
"luxon": "^1.26.0"
"temporal-polyfill": "^0.3.0"
},
"devDependencies": {
"@types/big.js": "^6.0.2",
Expand Down
118 changes: 62 additions & 56 deletions src/AstronomicalCalendar.ts

Large diffs are not rendered by default.

405 changes: 201 additions & 204 deletions src/ComplexZmanimCalendar.ts

Large diffs are not rendered by default.

77 changes: 39 additions & 38 deletions src/ZmanimCalendar.ts

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions src/hebrewcalendar/HebrewDateFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTimeFormatOptions } from 'luxon';
import { Temporal } from 'temporal-polyfill';

import { Daf } from './Daf';
import { JewishDate } from './JewishDate';
Expand Down Expand Up @@ -56,7 +56,7 @@ export class HebrewDateFormatter {
/**
* The internal DateFormat.  See {@link #isLongWeekFormat()} and {@link #setLongWeekFormat(boolean)}.
*/
private weekFormat: DateTimeFormatOptions | null = { weekday: 'long' };
private weekFormat: Intl.DateTimeFormatOptions | null = { weekday: 'long' };

/**
* List of transliterated parshiyos using the default <em>Ashkenazi</em> pronounciation.&nbsp; The formatParsha method uses this
Expand Down Expand Up @@ -639,8 +639,8 @@ export class HebrewDateFormatter {

const dateTime = jewishDate.getDate();
return this.weekFormat
? dateTime.toLocaleString(this.weekFormat)
: dateTime.toISO();
? dateTime.toLocaleString('en-US', this.weekFormat)
: dateTime.toString();
}

/**
Expand Down Expand Up @@ -911,7 +911,8 @@ export class HebrewDateFormatter {
* @see #isHebrewFormat()
*
*/
public formatHebrewNumber(num: number): string {
public formatHebrewNumber(num0: number): string {
let num: number = num0;
if (num !== Math.trunc(num)) throw new IllegalArgumentException('number must be an integer.');

if (num < 0) {
Expand Down
40 changes: 20 additions & 20 deletions src/hebrewcalendar/JewishCalendar.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTime } from 'luxon';
import { Temporal } from 'temporal-polyfill';

import { GeoLocation } from '../util/GeoLocation';
import { Daf } from './Daf';
Expand Down Expand Up @@ -359,11 +359,11 @@ export class JewishCalendar extends JewishDate {
*/
constructor(jewishYear: number, jewishMonth: number, jewishDayOfMonth: number, inIsrael?: boolean)
constructor(date: Date)
constructor(date: DateTime)
constructor(date: Temporal.PlainDate)
constructor()
constructor(jewishYearOrDateTimeOrDate?: number | Date | DateTime, jewishMonth?: number, jewishDayOfMonth?: number, inIsrael?: boolean) {
constructor(jewishYearOrDateTime?: number | Date | Temporal.PlainDate, jewishMonth?: number, jewishDayOfMonth?: number, inIsrael?: boolean) {
// @ts-ignore
super(jewishYearOrDateTimeOrDate, jewishMonth, jewishDayOfMonth);
super(jewishYearOrDateTime, jewishMonth, jewishDayOfMonth);
if (inIsrael) this.setInIsrael(inIsrael);
}

Expand Down Expand Up @@ -1347,7 +1347,7 @@ export class JewishCalendar extends JewishDate {
*
* @return the Date representing the moment of the molad in Yerushalayim standard time (GMT + 2)
*/
public getMoladAsDate(): DateTime {
public getMoladAsDate(): Temporal.ZonedDateTime {
const molad: JewishDate = this.getMolad();
const locationName: string = 'Jerusalem, Israel';

Expand All @@ -1364,17 +1364,17 @@ export class JewishCalendar extends JewishDate {
// subtract local time difference of 20.94 minutes (20 minutes and 56.496 seconds) to get to Standard time
const milliseconds: number = Math.trunc(1000 * (moladSeconds - Math.trunc(moladSeconds)));

return DateTime.fromObject({
return Temporal.ZonedDateTime.from({
year: molad.getGregorianYear(),
month: molad.getGregorianMonth() + 1,
day: molad.getGregorianDayOfMonth(),
hour: molad.getMoladHours(),
minute: molad.getMoladMinutes(),
second: Math.trunc(moladSeconds),
millisecond: milliseconds,
zone: geo.getTimeZone(),
timeZone: geo.getTimeZone(),
})
.minus({ milliseconds: Math.trunc(geo.getLocalMeanTimeOffset()) });
.subtract({ milliseconds: Math.trunc(geo.getLocalMeanTimeOffset()) });
}

/**
Expand All @@ -1387,10 +1387,10 @@ export class JewishCalendar extends JewishDate {
* @see ComplexZmanimCalendar#getTchilasZmanKidushLevana3Days()
* @see ComplexZmanimCalendar#getTchilasZmanKidushLevana3Days(Date, Date)
*/
public getTchilasZmanKidushLevana3Days(): DateTime {
const molad: DateTime = this.getMoladAsDate();
public getTchilasZmanKidushLevana3Days(): Temporal.ZonedDateTime {
const molad: Temporal.ZonedDateTime = this.getMoladAsDate();

return molad.plus({ hours: 72 });
return molad.add({ hours: 72 });
}

/**
Expand All @@ -1405,10 +1405,10 @@ export class JewishCalendar extends JewishDate {
* @see ComplexZmanimCalendar#getTchilasZmanKidushLevana7Days()
* @see ComplexZmanimCalendar#getTchilasZmanKidushLevana7Days(Date, Date)
*/
public getTchilasZmanKidushLevana7Days(): DateTime {
const molad: DateTime = this.getMoladAsDate();
public getTchilasZmanKidushLevana7Days(): Temporal.ZonedDateTime {
const molad: Temporal.ZonedDateTime = this.getMoladAsDate();

return molad.plus({ hours: 168 });
return molad.add({ hours: 168 });
}

/**
Expand All @@ -1425,13 +1425,13 @@ export class JewishCalendar extends JewishDate {
* @see ComplexZmanimCalendar#getSofZmanKidushLevanaBetweenMoldos()
* @see ComplexZmanimCalendar#getSofZmanKidushLevanaBetweenMoldos(Date, Date)
*/
public getSofZmanKidushLevanaBetweenMoldos(): DateTime {
const molad: DateTime = this.getMoladAsDate();
public getSofZmanKidushLevanaBetweenMoldos(): Temporal.ZonedDateTime {
const molad: Temporal.ZonedDateTime = this.getMoladAsDate();

// add half the time between molad and molad (half of 29 days, 12 hours and 793 chalakim (44 minutes, 3.3
// seconds), or 14 days, 18 hours, 22 minutes and 666 milliseconds). Add it as hours, not days, to avoid
// DST/ST crossover issues.
return molad.plus({
return molad.add({
hours: (24 * 14) + 18,
minutes: 22,
seconds: 1,
Expand All @@ -1456,11 +1456,11 @@ export class JewishCalendar extends JewishDate {
* @see ComplexZmanimCalendar#getSofZmanKidushLevana15Days()
* @see ComplexZmanimCalendar#getSofZmanKidushLevana15Days(Date, Date)
*/
public getSofZmanKidushLevana15Days(): DateTime {
const molad: DateTime = this.getMoladAsDate();
public getSofZmanKidushLevana15Days(): Temporal.ZonedDateTime {
const molad: Temporal.ZonedDateTime = this.getMoladAsDate();

// 15 days after the molad. Add it as hours, not days, to avoid DST/ST crossover issues.
return molad.plus({ hours: 24 * 15 });
return molad.add({ hours: 24 * 15 });
}

/**
Expand Down
21 changes: 11 additions & 10 deletions src/hebrewcalendar/JewishDate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTime } from 'luxon';
import { Temporal } from 'temporal-polyfill';

import { Calendar, IntegerUtils } from '../polyfills/Utils';
import { IllegalArgumentException } from '../polyfills/errors';
Expand Down Expand Up @@ -939,17 +939,18 @@ export class JewishDate {
constructor(jewishYear: number, jewishMonth: number, jewishDayOfMonth: number)
constructor(molad: number)
constructor(date: Date)
constructor(date: DateTime)
constructor(date: Temporal.PlainDate)
constructor()
constructor(jewishYearOrDateTimeOrDateOrMolad?: number | Date | DateTime, jewishMonth?: number, jewishDayOfMonth?: number) {
constructor(jewishYearOrDateTimeOrDateOrMolad?: number | Date | Temporal.PlainDate, jewishMonth?: number, jewishDayOfMonth?: number) {
if (!jewishYearOrDateTimeOrDateOrMolad) {
this.resetDate();
} else if (jewishMonth) {
this.setJewishDate(jewishYearOrDateTimeOrDateOrMolad as number, jewishMonth, jewishDayOfMonth!);
} else if (jewishYearOrDateTimeOrDateOrMolad instanceof Date) {
this.setDate(DateTime.fromJSDate(jewishYearOrDateTimeOrDateOrMolad as Date));
} else if (DateTime.isDateTime(jewishYearOrDateTimeOrDateOrMolad)) {
this.setDate(jewishYearOrDateTimeOrDateOrMolad as DateTime);
const instant = Temporal.Instant.fromEpochMilliseconds(jewishYearOrDateTimeOrDateOrMolad.getTime());
this.setDate(instant.toZonedDateTimeISO('UTC').toPlainDate());
} else if (jewishYearOrDateTimeOrDateOrMolad instanceof Temporal.PlainDate) {
this.setDate(jewishYearOrDateTimeOrDateOrMolad as Temporal.PlainDate);
} else if (typeof jewishYearOrDateTimeOrDateOrMolad === 'number') {
const molad = jewishYearOrDateTimeOrDateOrMolad as number;
this.absDateToDate(JewishDate.moladToAbsDate(molad));
Expand Down Expand Up @@ -1028,7 +1029,7 @@ export class JewishDate {
* @throws IllegalArgumentException
* if the {@link Calendar#ERA} is {@link GregorianCalendar#BC}
*/
public setDate(date: DateTime): void {
public setDate(date: Temporal.PlainDate): void {
if (date.year < 1) {
throw new IllegalArgumentException(`Dates with a BC era are not supported. The year ${date.year} is invalid.`);
}
Expand Down Expand Up @@ -1183,8 +1184,8 @@ export class JewishDate {
*
* @return The {@link java.util.Calendar}
*/
public getDate(): DateTime {
return DateTime.fromObject({
public getDate(): Temporal.PlainDate {
return Temporal.PlainDate.from({
year: this.gregorianYear,
month: this.gregorianMonth,
day: this.gregorianDayOfMonth,
Expand All @@ -1195,7 +1196,7 @@ export class JewishDate {
* Resets this date to the current system date.
*/
public resetDate(): void {
this.setDate(DateTime.local());
this.setDate(Temporal.Now.plainDateISO());
}

/**
Expand Down
33 changes: 19 additions & 14 deletions src/hebrewcalendar/YerushalmiYomiCalculator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTime, Interval } from 'luxon';
import { Temporal } from 'temporal-polyfill';

import { Calendar } from '../polyfills/Utils';
import { Daf } from './Daf';
Expand All @@ -16,7 +16,7 @@ export class YerushalmiYomiCalculator {
/**
* The start date of the first Daf Yomi Yerushalmi cycle of February 2, 1980 / 15 Shevat, 5740.
*/
private static readonly DAF_YOMI_START_DAY: DateTime = DateTime.fromObject({
private static readonly DAF_YOMI_START_DAY: Temporal.PlainDate = Temporal.PlainDate.from({
year: 1980,
month: Calendar.FEBRUARY + 1,
day: 2,
Expand Down Expand Up @@ -53,9 +53,9 @@ export class YerushalmiYomiCalculator {
* if the date is prior to the February 2, 1980, the start of the first Daf Yomi Yerushalmi cycle
*/
public static getDafYomiYerushalmi(jewishCalendar: JewishCalendar): Daf | null {
let nextCycle: DateTime = YerushalmiYomiCalculator.DAF_YOMI_START_DAY;
let prevCycle: DateTime = YerushalmiYomiCalculator.DAF_YOMI_START_DAY;
const requested: DateTime = jewishCalendar.getDate();
let nextCycle: Temporal.PlainDate = YerushalmiYomiCalculator.DAF_YOMI_START_DAY;
let prevCycle: Temporal.PlainDate = YerushalmiYomiCalculator.DAF_YOMI_START_DAY;
const requested: Temporal.PlainDate = jewishCalendar.getDate();
let masechta: number = 0;
let dafYomi: Daf;

Expand All @@ -64,25 +64,25 @@ export class YerushalmiYomiCalculator {
return null;
}

if (requested < YerushalmiYomiCalculator.DAF_YOMI_START_DAY) {
if (Temporal.PlainDate.compare(requested, YerushalmiYomiCalculator.DAF_YOMI_START_DAY) < 0) {
throw new IllegalArgumentException(`${requested} is prior to organized Daf Yomi Yerushalmi cycles that started on ${YerushalmiYomiCalculator.DAF_YOMI_START_DAY}`);
}

// Start to calculate current cycle. Initialize the start day
// nextCycle = YerushalmiYomiCalculator.DAF_YOMI_START_DAY;

// Go cycle by cycle, until we get the next cycle
while (requested > nextCycle) {
while (Temporal.PlainDate.compare(requested, nextCycle) > 0) {
prevCycle = nextCycle;

// Adds the number of whole shas dafs, and then the number of days that not have daf.
nextCycle = nextCycle.plus({ days: YerushalmiYomiCalculator.WHOLE_SHAS_DAFS });
nextCycle = nextCycle.add({ days: YerushalmiYomiCalculator.WHOLE_SHAS_DAFS });
// This needs to be a separate step
nextCycle = nextCycle.plus({ days: YerushalmiYomiCalculator.getNumOfSpecialDays(prevCycle, nextCycle) });
nextCycle = nextCycle.add({ days: YerushalmiYomiCalculator.getNumOfSpecialDays(prevCycle, nextCycle) });
}

// Get the number of days from cycle start until request.
const dafNo: number = requested.diff(prevCycle, ['days']).days;
const dafNo: number = requested.since(prevCycle).days;

// Get the number of special days to subtract
const specialDays: number = YerushalmiYomiCalculator.getNumOfSpecialDays(prevCycle, requested);
Expand Down Expand Up @@ -110,7 +110,7 @@ export class YerushalmiYomiCalculator {
* @param end - end date to calculate at
* @return the number of special days between the start and end dates
*/
private static getNumOfSpecialDays(start: DateTime, end: DateTime): number {
private static getNumOfSpecialDays(start: Temporal.PlainDate, end: Temporal.PlainDate): number {
// Find the start and end Jewish years
const jewishStartYear: number = new JewishCalendar(start).getJewishYear();
const jewishEndYear: number = new JewishCalendar(end).getJewishYear();
Expand All @@ -127,9 +127,14 @@ export class YerushalmiYomiCalculator {
yomKippur.setJewishYear(i);
tishaBeav.setJewishYear(i);

const interval = Interval.fromDateTimes(start, end);
if (interval.contains(yomKippur.getDate())) specialDays++;
if (interval.contains(tishaBeav.getDate())) specialDays++;
const yk = yomKippur.getDate();
if (Temporal.PlainDate.compare(yk, start) >= 0 && Temporal.PlainDate.compare(yk, end) <= 0) {
specialDays++;
}
const av9 = tishaBeav.getDate();
if (Temporal.PlainDate.compare(av9, start) >= 0 && Temporal.PlainDate.compare(av9, end) <= 0) {
specialDays++;
}
}

return specialDays;
Expand Down
15 changes: 8 additions & 7 deletions src/hebrewcalendar/YomiCalculator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DateTime } from 'luxon';
import { Temporal } from 'temporal-polyfill';

import { Calendar } from '../polyfills/Utils';
import { Daf } from './Daf';
Expand All @@ -17,7 +17,7 @@ export class YomiCalculator {
/**
* The start date of the first Daf Yomi Bavli cycle of September 11, 1923 / Rosh Hashana 5684.
*/
private static readonly dafYomiStartDate: DateTime = DateTime.fromObject({
private static readonly dafYomiStartDate: Temporal.PlainDate = Temporal.PlainDate.from({
year: 1923,
month: Calendar.SEPTEMBER + 1,
day: 11,
Expand All @@ -30,7 +30,7 @@ export class YomiCalculator {
* The date that the pagination for the Daf Yomi <em>Maseches Shekalim</em> changed to use the commonly used Vilna
* Shas pagination from the no longer commonly available Zhitomir / Slavuta Shas used by Rabbi Meir Shapiro.
*/
private static readonly shekalimChangeDate: DateTime = DateTime.fromObject({ year: 1975, month: Calendar.JUNE + 1, day: 24 });
private static readonly shekalimChangeDate: Temporal.PlainDate = Temporal.PlainDate.from({ year: 1975, month: Calendar.JUNE + 1, day: 24 });

/** The Julian date that the cycle for Shekalim changed.
* @see #getDafYomiBavli(JewishCalendar) for details.
Expand Down Expand Up @@ -78,17 +78,18 @@ export class YomiCalculator {
const blattPerMasechta: number[] = [64, 157, 105, 121, 22, 88, 56, 40, 35, 31, 32, 29, 27, 122, 112, 91, 66, 49, 90, 82,
119, 119, 176, 113, 24, 49, 76, 14, 120, 110, 142, 61, 34, 34, 28, 22, 4, 9, 5, 73];

const date: DateTime = calendar.getDate();
const date: Temporal.PlainDate = calendar.getDate();

let dafYomi: Daf;
const julianDay: number = this.getJulianDay(date);
let cycleNo: number;
let dafNo: number;
if (date < YomiCalculator.dafYomiStartDate) {
if (Temporal.PlainDate.compare(date, YomiCalculator.dafYomiStartDate) < 0) {
// TODO: should we return a null or throw an IllegalArgumentException?
throw new IllegalArgumentException(`${calendar} is prior to organized Daf Yomi Bavli cycles that started on ${YomiCalculator.dafYomiStartDate}`);
}
if ((date > YomiCalculator.shekalimChangeDate) || date.equals(YomiCalculator.shekalimChangeDate)) {
if ((Temporal.PlainDate.compare(date, YomiCalculator.shekalimChangeDate) > 0) ||
date.equals(YomiCalculator.shekalimChangeDate)) {
cycleNo = 8 + ((julianDay - YomiCalculator.shekalimJulianChangeDay) / 2711);
dafNo = ((julianDay - YomiCalculator.shekalimJulianChangeDay) % 2711);
} else {
Expand Down Expand Up @@ -134,7 +135,7 @@ export class YomiCalculator {
* The Java Date
* @return the Julian day number corresponding to the date
*/
private static getJulianDay(date: DateTime): number {
private static getJulianDay(date: Temporal.PlainDate): number {
let { year, month } = date;
const { day } = date;

Expand Down
12 changes: 3 additions & 9 deletions src/kosher-zmanim.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as _Luxon from 'luxon';

import { Temporal } from 'temporal-polyfill';
import { GeoLocation } from './util/GeoLocation';
import { ZmanimCalendar } from './ZmanimCalendar';
import { ComplexZmanimCalendar } from './ComplexZmanimCalendar';
Expand All @@ -12,15 +11,15 @@ export function getZmanimJson(options: Options): JsonOutput {
const zmanimCalendar: ZmanimCalendar = options.complexZmanim
? new ComplexZmanimCalendar(geoLocation)
: new ZmanimCalendar(geoLocation);
zmanimCalendar.setDate(options.date || _Luxon.DateTime.local());
zmanimCalendar.setDate(options.date || Temporal.Now.plainDateISO());
return ZmanimFormatter.toJSON(zmanimCalendar);
}

export interface Options {
/**
* @default The current local date. The time is ignored.
*/
date?: Date | string | number | _Luxon.DateTime;
date?: Date | string | number | Temporal.PlainDate;
/**
* IANA timezone ID
*/
Expand Down Expand Up @@ -60,8 +59,3 @@ export * from './hebrewcalendar/YerushalmiYomiCalculator';

export * from './hebrewcalendar/HebrewDateFormatter';
export * from './util/ZmanimFormatter';

export const Luxon = _Luxon;

// Exported explicitly as a convenience.
export const DateTime = _Luxon.DateTime;
Loading