Files
gameno-api/utils/jalaliDate.js
T
kavehhn 3348ca5798 feat: import class sessions, attendance, and payments from JSON
Match students by name when national ID or phone is missing, parse Jalali dates, and allow sessions without a professor.
2026-08-16 07:04:16 +03:30

98 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const toEnglishDigits = (value) =>
String(value ?? '')
.replace(/[۰-۹]/g, (d) => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d))
.replace(/[٠-٩]/g, (d) => '٠١٢٣٤٥٦٧٨٩'.indexOf(d));
const jalaliToGregorian = (jy, jm, jd) => {
const gy = jy <= 979 ? 621 : 1600;
jy -= jy <= 979 ? 0 : 979;
let days =
365 * jy +
Math.floor(jy / 33) * 8 +
Math.floor(((jy % 33) + 3) / 4) +
78 +
jd +
(jm < 7 ? (jm - 1) * 31 : (jm - 7) * 30 + 186);
let gyOut = gy + 400 * Math.floor(days / 146097);
days %= 146097;
if (days > 36524) {
gyOut += 100 * Math.floor(--days / 36524);
days %= 36524;
if (days >= 365) days += 1;
}
gyOut += 4 * Math.floor(days / 1461);
days %= 1461;
if (days > 365) {
gyOut += Math.floor((days - 1) / 365);
days = (days - 1) % 365;
}
let gd = days + 1;
const sal_a = [
0,
31,
(gyOut % 4 === 0 && gyOut % 100 !== 0) || gyOut % 400 === 0 ? 29 : 28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
];
let gm = 0;
for (gm = 1; gm <= 12 && gd > sal_a[gm]; gm += 1) gd -= sal_a[gm];
return `${gyOut}-${String(gm).padStart(2, '0')}-${String(gd).padStart(2, '0')}`;
};
const parseJalaliDate = (raw) => {
if (!raw) return null;
const text = toEnglishDigits(raw).replace(/[./\-]/g, '/').trim();
const match = text.match(/^(\d{3,4})\/(\d{1,2})\/(\d{1,2})$/);
if (!match) return null;
const jy = Number(match[1]);
const jm = Number(match[2]);
const jd = Number(match[3]);
if (!jy || !jm || !jd || jm > 12 || jd > 31 || jy < 1200 || jy > 1599) return null;
try {
return jalaliToGregorian(jy, jm, jd);
} catch {
return null;
}
};
const parseImportDate = (raw) => {
if (!raw) return null;
if (raw instanceof Date) {
return Number.isNaN(raw.getTime()) ? null : raw;
}
const text = String(raw).trim();
if (!text) return null;
const gregorian = text.match(/^(\d{4}-\d{2}-\d{2})/);
if (gregorian) return new Date(`${gregorian[1]}T00:00:00.000Z`);
const jalali = parseJalaliDate(text);
if (jalali) return new Date(`${jalali}T00:00:00.000Z`);
const date = new Date(text);
return Number.isNaN(date.getTime()) ? null : date;
};
const utcDayRange = (value) => {
const date = parseImportDate(value);
if (!date) return null;
const start = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
const end = new Date(start.getTime() + 24 * 60 * 60 * 1000);
return { start, end };
};
module.exports = {
toEnglishDigits,
jalaliToGregorian,
parseJalaliDate,
parseImportDate,
utcDayRange
};