UEA-Prodem

This commit is contained in:
2026-06-10 12:38:42 -03:00
parent 3f33154e16
commit c41625e542
9352 changed files with 1128292 additions and 14752 deletions
+1
View File
@@ -0,0 +1 @@
export declare function addMonths(date: Date, amount: number): Date;
+6
View File
@@ -0,0 +1,6 @@
import { toHijriDate } from "../utils/conversion.js";
import { setMonth } from "./setMonth.js";
export function addMonths(date, amount) {
const hijri = toHijriDate(date);
return setMonth(date, hijri.monthIndex + amount);
}
+1
View File
@@ -0,0 +1 @@
export declare function addYears(date: Date, amount: number): Date;
+6
View File
@@ -0,0 +1,6 @@
import { toHijriDate } from "../utils/conversion.js";
import { setYear } from "./setYear.js";
export function addYears(date, amount) {
const hijri = toHijriDate(date);
return setYear(date, hijri.year + amount);
}
@@ -0,0 +1 @@
export declare function differenceInCalendarMonths(dateLeft: Date, dateRight: Date): number;
@@ -0,0 +1,7 @@
import { toHijriDate } from "../utils/conversion.js";
export function differenceInCalendarMonths(dateLeft, dateRight) {
const hijriLeft = toHijriDate(dateLeft);
const hijriRight = toHijriDate(dateRight);
return ((hijriLeft.year - hijriRight.year) * 12 +
(hijriLeft.monthIndex - hijriRight.monthIndex));
}
@@ -0,0 +1,2 @@
import { type Interval } from "date-fns";
export declare function eachMonthOfInterval(interval: Interval): Date[];
@@ -0,0 +1,26 @@
import { toDate } from "date-fns";
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
export function eachMonthOfInterval(interval) {
const start = toDate(interval.start);
const end = toDate(interval.end);
if (end.getTime() < start.getTime()) {
throw new RangeError("Invalid interval");
}
const startDate = toHijriDate(start);
const endDate = toHijriDate(end);
const months = [];
let currentYear = startDate.year;
let currentMonth = startDate.monthIndex;
const endYear = endDate.year;
const endMonth = endDate.monthIndex;
while (currentYear < endYear ||
(currentYear === endYear && currentMonth <= endMonth)) {
months.push(toGregorianDate({ year: currentYear, monthIndex: currentMonth, day: 1 }));
currentMonth += 1;
if (currentMonth > 11) {
currentMonth = 0;
currentYear += 1;
}
}
return months;
}
@@ -0,0 +1,2 @@
import { type Interval } from "date-fns";
export declare function eachYearOfInterval(interval: Interval): Date[];
+16
View File
@@ -0,0 +1,16 @@
import { toDate } from "date-fns";
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
export function eachYearOfInterval(interval) {
const start = toDate(interval.start);
const end = toDate(interval.end);
if (end.getTime() < start.getTime()) {
return [];
}
const startYear = toHijriDate(start).year;
const endYear = toHijriDate(end).year;
const years = [];
for (let year = startYear; year <= endYear; year += 1) {
years.push(toGregorianDate({ year, monthIndex: 0, day: 1 }));
}
return years;
}
+1
View File
@@ -0,0 +1 @@
export declare function endOfMonth(date: Date): Date;
+11
View File
@@ -0,0 +1,11 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
import { getDaysInMonth } from "../utils/daysInMonth.js";
export function endOfMonth(date) {
const hijri = toHijriDate(date);
const day = getDaysInMonth(hijri.year, hijri.monthIndex);
return toGregorianDate({
year: hijri.year,
monthIndex: hijri.monthIndex,
day,
});
}
+1
View File
@@ -0,0 +1 @@
export declare function endOfYear(date: Date): Date;
+11
View File
@@ -0,0 +1,11 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
import { getDaysInMonth } from "../utils/daysInMonth.js";
export function endOfYear(date) {
const hijri = toHijriDate(date);
const day = getDaysInMonth(hijri.year, 11);
return toGregorianDate({
year: hijri.year,
monthIndex: 11,
day,
});
}
@@ -0,0 +1,5 @@
export type FallbackLocaleCode = "ar" | "en";
export type IntlNameWidth = "long" | "short" | "narrow";
export declare const getFallbackLocaleCode: (localeCode: string) => FallbackLocaleCode;
export declare const getFallbackMonthName: (date: Date, localeCode: string, width: IntlNameWidth) => string;
export declare const getFallbackWeekdayName: (date: Date, localeCode: string, width: IntlNameWidth) => string;
+105
View File
@@ -0,0 +1,105 @@
import { toHijriDate } from "../utils/conversion.js";
const fallbackMonthNames = {
en: {
long: [
"Muharram",
"Safar",
"Rabi I",
"Rabi II",
"Jumada I",
"Jumada II",
"Rajab",
"Shaban",
"Ramadan",
"Shawwal",
"Dhu al-Qadah",
"Dhu al-Hijjah",
],
short: [
"Muh",
"Saf",
"Rab-I",
"Rab-II",
"Jum-I",
"Jum-II",
"Raj",
"Sha",
"Ram",
"Shw",
"Dhu-Q",
"Dhu-H",
],
narrow: ["M", "S", "R", "R", "J", "J", "R", "S", "R", "S", "D", "D"],
},
ar: {
long: [
"محرم",
"صفر",
"ربيع الأول",
"ربيع الآخر",
"جمادى الأولى",
"جمادى الآخرة",
"رجب",
"شعبان",
"رمضان",
"شوال",
"ذو القعدة",
"ذو الحجة",
],
short: [
"محرم",
"صفر",
"ربيع ١",
"ربيع ٢",
"جمادى ١",
"جمادى ٢",
"رجب",
"شعبان",
"رمضان",
"شوال",
"ذو القعدة",
"ذو الحجة",
],
narrow: ["م", "ص", "ر", "ر", "ج", "ج", "ر", "ش", "ر", "ش", "ذ", "ذ"],
},
};
const fallbackWeekdayNames = {
en: {
long: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
short: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
narrow: ["S", "M", "T", "W", "T", "F", "S"],
},
ar: {
long: [
"الأحد",
"الاثنين",
"الثلاثاء",
"الأربعاء",
"الخميس",
"الجمعة",
"السبت",
],
short: ["أحد", "اثن", "ثلا", "أرب", "خمي", "جمع", "سبت"],
narrow: ["ح", "ن", "ث", "ر", "خ", "ج", "س"],
},
};
export const getFallbackLocaleCode = (localeCode) => {
return localeCode.toLowerCase().startsWith("ar") ? "ar" : "en";
};
export const getFallbackMonthName = (date, localeCode, width) => {
const hijri = toHijriDate(date);
const locale = getFallbackLocaleCode(localeCode);
return fallbackMonthNames[locale][width][hijri.monthIndex];
};
export const getFallbackWeekdayName = (date, localeCode, width) => {
const locale = getFallbackLocaleCode(localeCode);
return fallbackWeekdayNames[locale][width][date.getDay()];
};
+3
View File
@@ -0,0 +1,3 @@
import type { FormatOptions as DateFnsFormatOptions } from "date-fns";
/** Hijri calendar formatting override. */
export declare function format(date: Date, formatStr: string, options?: DateFnsFormatOptions): string;
+146
View File
@@ -0,0 +1,146 @@
import { toHijriDate } from "../utils/conversion.js";
import { clampGregorianDate, getGregorianDateParts } from "../utils/range.js";
import { getFallbackMonthName, getFallbackWeekdayName, } from "./fallbackLocaleData.js";
const DEFAULT_LOCALE_CODE = "ar-SA";
const BASE_NUMBERING_SYSTEM = "latn";
const UMM_AL_QURA_CALENDAR = "islamic-umalqura";
const getLocaleCode = (options) => {
return options?.locale?.code ?? DEFAULT_LOCALE_CODE;
};
const formatWithUmmAlQura = (date, localeCode, options) => {
try {
return new Intl.DateTimeFormat(localeCode, {
...options,
calendar: UMM_AL_QURA_CALENDAR,
numberingSystem: BASE_NUMBERING_SYSTEM,
}).format(date);
}
catch {
return undefined;
}
};
const formatNumber = (value) => {
return value.toString();
};
const formatPaddedNumber = (value) => {
return formatNumber(value).padStart(2, "0");
};
const formatMonthName = (date, localeCode, width) => {
const formatted = formatWithUmmAlQura(date, localeCode, {
month: width,
});
return formatted ?? getFallbackMonthName(date, localeCode, width);
};
const formatWeekdayName = (date, localeCode, width) => {
const formatted = formatWithUmmAlQura(date, localeCode, {
weekday: width,
});
return formatted ?? getFallbackWeekdayName(date, localeCode, width);
};
const formatDateStyle = (date, localeCode, style) => {
const formatted = formatWithUmmAlQura(date, localeCode, {
dateStyle: style,
});
if (formatted) {
return formatted;
}
const hijri = toHijriDate(date);
const monthName = getFallbackMonthName(date, localeCode, "long");
switch (style) {
case "full":
return `${getFallbackWeekdayName(date, localeCode, "long")}, ${monthName} ${hijri.day}, ${hijri.year}`;
case "long":
return `${monthName} ${hijri.day}, ${hijri.year}`;
case "medium":
return `${formatPaddedNumber(hijri.day)} ${monthName} ${hijri.year}`;
case "short":
return `${hijri.monthIndex + 1}/${hijri.day}/${hijri.year}`;
}
};
const buildTimeFormat = (date, localeCode, formatStr) => {
const hour12 = formatStr.includes("a");
const formatted = formatWithUmmAlQura(date, localeCode, {
hour: "numeric",
minute: "numeric",
hour12,
});
if (formatted) {
return formatted;
}
try {
return new Intl.DateTimeFormat(localeCode, {
hour: "numeric",
minute: "numeric",
hour12,
numberingSystem: BASE_NUMBERING_SYSTEM,
}).format(date);
}
catch {
const minutes = formatPaddedNumber(date.getMinutes());
if (hour12) {
const hour = date.getHours() % 12 || 12;
const period = date.getHours() >= 12 ? "PM" : "AM";
return `${hour}:${minutes} ${period}`;
}
return `${formatNumber(date.getHours())}:${minutes}`;
}
};
/** Hijri calendar formatting override. */
export function format(date, formatStr, options) {
const extendedOptions = options;
const localeCode = getLocaleCode(extendedOptions);
const hijri = toHijriDate(date);
const gregorian = getGregorianDateParts(date);
const isOutOfRange = clampGregorianDate(date) !== date;
const numericDate = isOutOfRange
? {
year: gregorian.year,
monthIndex: gregorian.month - 1,
day: gregorian.day,
}
: hijri;
switch (formatStr) {
case "LLLL y":
case "LLLL yyyy":
return `${formatMonthName(date, localeCode, "long")} ${formatNumber(numericDate.year)}`;
case "LLLL":
return formatMonthName(date, localeCode, "long");
case "LLL":
return formatMonthName(date, localeCode, "short");
case "PPP":
return formatDateStyle(date, localeCode, "long");
case "PPPP":
return formatDateStyle(date, localeCode, "full");
case "PP":
return formatDateStyle(date, localeCode, "medium");
case "P":
return formatDateStyle(date, localeCode, "short");
case "cccc":
return formatWeekdayName(date, localeCode, "long");
case "ccc":
return formatWeekdayName(date, localeCode, "short");
case "ccccc":
case "cccccc":
return formatWeekdayName(date, localeCode, "narrow");
case "yyyy":
case "y":
return formatNumber(numericDate.year);
case "yyyy-MM":
return `${formatNumber(numericDate.year)}-${formatPaddedNumber(numericDate.monthIndex + 1)}`;
case "yyyy-MM-dd":
return `${formatNumber(numericDate.year)}-${formatPaddedNumber(numericDate.monthIndex + 1)}-${formatPaddedNumber(numericDate.day)}`;
case "MM":
return formatPaddedNumber(numericDate.monthIndex + 1);
case "M":
return formatNumber(numericDate.monthIndex + 1);
case "dd":
return formatPaddedNumber(numericDate.day);
case "d":
return formatNumber(numericDate.day);
default:
if (/[Hh]/.test(formatStr) && /m/.test(formatStr)) {
return buildTimeFormat(date, localeCode, formatStr);
}
return formatDateStyle(date, localeCode, "medium");
}
}
+1
View File
@@ -0,0 +1 @@
export declare function getMonth(date: Date): number;
+4
View File
@@ -0,0 +1,4 @@
import { toHijriDate } from "../utils/conversion.js";
export function getMonth(date) {
return toHijriDate(date).monthIndex;
}
+1
View File
@@ -0,0 +1 @@
export declare function getYear(date: Date): number;
+4
View File
@@ -0,0 +1,4 @@
import { toHijriDate } from "../utils/conversion.js";
export function getYear(date) {
return toHijriDate(date).year;
}
+17
View File
@@ -0,0 +1,17 @@
export * from "./addMonths.js";
export * from "./addYears.js";
export * from "./differenceInCalendarMonths.js";
export * from "./eachMonthOfInterval.js";
export * from "./eachYearOfInterval.js";
export * from "./endOfMonth.js";
export * from "./endOfYear.js";
export * from "./format.js";
export * from "./getMonth.js";
export * from "./getYear.js";
export * from "./isSameMonth.js";
export * from "./isSameYear.js";
export * from "./newDate.js";
export * from "./setMonth.js";
export * from "./setYear.js";
export * from "./startOfMonth.js";
export * from "./startOfYear.js";
+17
View File
@@ -0,0 +1,17 @@
export * from "./addMonths.js";
export * from "./addYears.js";
export * from "./differenceInCalendarMonths.js";
export * from "./eachMonthOfInterval.js";
export * from "./eachYearOfInterval.js";
export * from "./endOfMonth.js";
export * from "./endOfYear.js";
export * from "./format.js";
export * from "./getMonth.js";
export * from "./getYear.js";
export * from "./isSameMonth.js";
export * from "./isSameYear.js";
export * from "./newDate.js";
export * from "./setMonth.js";
export * from "./setYear.js";
export * from "./startOfMonth.js";
export * from "./startOfYear.js";
+1
View File
@@ -0,0 +1 @@
export declare function isSameMonth(dateLeft: Date, dateRight: Date): boolean;
+7
View File
@@ -0,0 +1,7 @@
import { toHijriDate } from "../utils/conversion.js";
export function isSameMonth(dateLeft, dateRight) {
const hijriLeft = toHijriDate(dateLeft);
const hijriRight = toHijriDate(dateRight);
return (hijriLeft.year === hijriRight.year &&
hijriLeft.monthIndex === hijriRight.monthIndex);
}
+1
View File
@@ -0,0 +1 @@
export declare function isSameYear(dateLeft: Date, dateRight: Date): boolean;
+6
View File
@@ -0,0 +1,6 @@
import { toHijriDate } from "../utils/conversion.js";
export function isSameYear(dateLeft, dateRight) {
const hijriLeft = toHijriDate(dateLeft);
const hijriRight = toHijriDate(dateRight);
return hijriLeft.year === hijriRight.year;
}
+1
View File
@@ -0,0 +1 @@
export declare function newDate(year: number, monthIndex: number, day: number): Date;
+4
View File
@@ -0,0 +1,4 @@
import { toGregorianDate } from "../utils/conversion.js";
export function newDate(year, monthIndex, day) {
return toGregorianDate({ year, monthIndex, day });
}
+1
View File
@@ -0,0 +1 @@
export declare function setMonth(date: Date, monthIndex: number): Date;
+24
View File
@@ -0,0 +1,24 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
import { getDaysInMonth } from "../utils/daysInMonth.js";
export function setMonth(date, monthIndex) {
const hijri = toHijriDate(date);
// Handle overflow/underflow of monthIndex
// Note: monthIndex argument is absolute month index for the year.
// E.g. setMonth(..., 13) sets to Safar next year.
let targetYear = hijri.year;
let targetMonth = monthIndex;
if (targetMonth > 11 || targetMonth < 0) {
targetYear += Math.floor(targetMonth / 12);
targetMonth = targetMonth % 12;
if (targetMonth < 0) {
targetMonth += 12;
}
}
const daysInTargetMonth = getDaysInMonth(targetYear, targetMonth);
const day = Math.min(hijri.day, daysInTargetMonth);
return toGregorianDate({
year: targetYear,
monthIndex: targetMonth,
day,
});
}
+1
View File
@@ -0,0 +1 @@
export declare function setYear(date: Date, year: number): Date;
+12
View File
@@ -0,0 +1,12 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
import { getDaysInMonth } from "../utils/daysInMonth.js";
export function setYear(date, year) {
const hijri = toHijriDate(date);
const daysInTargetMonth = getDaysInMonth(year, hijri.monthIndex);
const day = Math.min(hijri.day, daysInTargetMonth);
return toGregorianDate({
year,
monthIndex: hijri.monthIndex,
day,
});
}
+1
View File
@@ -0,0 +1 @@
export declare function startOfMonth(date: Date): Date;
+9
View File
@@ -0,0 +1,9 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
export function startOfMonth(date) {
const hijri = toHijriDate(date);
return toGregorianDate({
year: hijri.year,
monthIndex: hijri.monthIndex,
day: 1,
});
}
+1
View File
@@ -0,0 +1 @@
export declare function startOfYear(date: Date): Date;
+9
View File
@@ -0,0 +1,9 @@
import { toGregorianDate, toHijriDate } from "../utils/conversion.js";
export function startOfYear(date) {
const hijri = toHijriDate(date);
return toGregorianDate({
year: hijri.year,
monthIndex: 0,
day: 1,
});
}