forked from Yara724/api
Tidied up the project
This commit is contained in:
@@ -1,13 +1,9 @@
|
||||
import * as jMoment from "jalali-moment";
|
||||
|
||||
/**
|
||||
* Converts an ISO date string or Date to Jalali (Persian) date and time.
|
||||
* @param input - ISO date string (e.g. 2026-02-08T13:51:20.747+00:00) or Date
|
||||
* @returns Tuple [dateStr, timeStr] e.g. ['1404/11/24', '13:37']
|
||||
*/
|
||||
export function toJalaliDateAndTime(
|
||||
input: string | Date,
|
||||
): [string, string] {
|
||||
export function toJalaliDateAndTime(input: string | Date): [string, string] {
|
||||
const d = new Date(input);
|
||||
const dateStr = toJalaliDate(d);
|
||||
const timeStr = toJalaliTime(d);
|
||||
@@ -32,8 +28,7 @@ export function jalaliToGregorianDate(
|
||||
): string | null {
|
||||
if (input === null || input === undefined) return null;
|
||||
|
||||
const raw =
|
||||
typeof input === "number" ? String(input) : String(input).trim();
|
||||
const raw = typeof input === "number" ? String(input) : String(input).trim();
|
||||
if (!raw) return null;
|
||||
|
||||
let year = 0;
|
||||
@@ -58,20 +53,16 @@ export function jalaliToGregorianDate(
|
||||
|
||||
if (!year || !month || !day) return null;
|
||||
|
||||
// If the year already looks Gregorian (>= 1900), assume the caller already
|
||||
// sent a Gregorian date and just normalise the formatting.
|
||||
// If the year already looks Gregorian (>= 1900), just normalise formatting.
|
||||
if (year >= 1900) {
|
||||
const mm = String(month).padStart(2, "0");
|
||||
const dd = String(day).padStart(2, "0");
|
||||
const m = jMoment(`${year}-${mm}-${dd}`, "YYYY-MM-DD");
|
||||
return m.isValid() ? m.format("YYYY-MM-DD") : null;
|
||||
const d = new Date(`${year}-${mm}-${dd}`);
|
||||
if (isNaN(d.getTime())) return null;
|
||||
return `${year}-${mm}-${dd}`;
|
||||
}
|
||||
|
||||
const mm = String(month).padStart(2, "0");
|
||||
const dd = String(day).padStart(2, "0");
|
||||
const jm = jMoment(`${year}-${mm}-${dd}`, "jYYYY-jMM-jDD");
|
||||
if (!jm.isValid()) return null;
|
||||
return jm.format("YYYY-MM-DD");
|
||||
return jalaliPartsToGregorian(year, month, day);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,6 +86,92 @@ export function toJalaliTime(d: Date): string {
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Jalali year/month/day parts to a Gregorian `YYYY-MM-DD` string
|
||||
* using the algorithmic conversion (no external deps).
|
||||
* Returns `null` if the resulting Gregorian date is invalid.
|
||||
*/
|
||||
function jalaliPartsToGregorian(
|
||||
jYear: number,
|
||||
jMonth: number,
|
||||
jDay: number,
|
||||
): string | null {
|
||||
// Jalali to Julian Day Number, then to Gregorian
|
||||
// Algorithm: https://www.fourmilab.ch/documents/calendar/
|
||||
const jy = jYear - 979;
|
||||
const jm = jMonth - 1;
|
||||
const jd = jDay - 1;
|
||||
|
||||
let jDayNo =
|
||||
365 * jy + Math.floor(jy / 4) - Math.floor(jy / 100) + Math.floor(jy / 400);
|
||||
|
||||
const jalaliMonthDays = [31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29];
|
||||
for (let i = 0; i < jm; i++) {
|
||||
jDayNo += jalaliMonthDays[i];
|
||||
}
|
||||
jDayNo += jd;
|
||||
|
||||
// Convert to Gregorian day number (offset from 1970-01-01 in Julian days)
|
||||
const gDayNo = jDayNo + 79;
|
||||
|
||||
let gy = 1979 + 400 * Math.floor(gDayNo / 146097);
|
||||
let days = gDayNo % 146097;
|
||||
|
||||
let leap = true;
|
||||
if (days >= 36525) {
|
||||
days--;
|
||||
gy += 100 * Math.floor(days / 36524);
|
||||
days %= 36524;
|
||||
if (days >= 365) days++;
|
||||
else leap = false;
|
||||
}
|
||||
|
||||
gy += 4 * Math.floor(days / 1461);
|
||||
days %= 1461;
|
||||
|
||||
if (days >= 366) {
|
||||
leap = false;
|
||||
days--;
|
||||
gy += Math.floor(days / 365);
|
||||
days %= 365;
|
||||
}
|
||||
|
||||
const gregorianMonthDays = [
|
||||
31,
|
||||
leap ? 29 : 28,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
30,
|
||||
31,
|
||||
];
|
||||
|
||||
let gm = 0;
|
||||
for (let i = 0; i < 12; i++) {
|
||||
if (days < gregorianMonthDays[i]) {
|
||||
gm = i + 1;
|
||||
break;
|
||||
}
|
||||
days -= gregorianMonthDays[i];
|
||||
}
|
||||
const gd = days + 1;
|
||||
|
||||
const mm = String(gm).padStart(2, "0");
|
||||
const dd = String(gd).padStart(2, "0");
|
||||
const result = `${gy}-${mm}-${dd}`;
|
||||
|
||||
// Sanity check
|
||||
const check = new Date(result);
|
||||
if (isNaN(check.getTime())) return null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const PERSIAN_TO_ENGLISH: Record<string, string> = {
|
||||
"۰": "0",
|
||||
"۱": "1",
|
||||
|
||||
Reference in New Issue
Block a user