UNPKG

jalali-date

Version:

A Jalali to Gregorian converter with support of formatting output

97 lines (85 loc) 2.94 kB
import { divCeil } from './helpers'; import { GREGORIAN_EPOCH, PERSIAN_EPOCH, NON_LEAP_CORRECTION, PERSIAN_CYCLE_DAYS } from './constants'; export default class Converter { static gregorianToFixed(year, month, day) { const result = GREGORIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) + Math.floor((year - 1) / 400) + Math.floor((367 * month - 362) / 12) // eslint-disable-next-line no-nested-ternary + (month <= 2 ? 0 : Converter.leapGregorian(year) ? -1 : -2) + day; return result; } static gregorianYearFromFixed(date) { const d0 = date - GREGORIAN_EPOCH; const n400 = Math.floor(d0 / 146097); const d1 = d0 % 146097; const n100 = Math.floor(d1 / 36524); const d2 = d1 % 36524; const n4 = Math.floor(d2 / 1461); const d3 = d2 % 1461; const n1 = Math.floor(d3 / 365); const year = 400 * n400 + 100 * n100 + 4 * n4 + n1; if (n100 === 4 || n1 === 4) { return year; } return year + 1; } static gregorianNewYear(year) { return Converter.gregorianToFixed(year, 1, 1); } static fixedToGregorian(date) { const year = Converter.gregorianYearFromFixed(date); const priorDays = date - Converter.gregorianNewYear(year); let correction; if (date < Converter.gregorianToFixed([year, 3, 1])) { correction = 0; } else if (Converter.leapGregorian(year)) { correction = 1; } else { correction = 2; } const month = Math.floor((12 * (priorDays + correction) + 373) / 367); const day = date - Converter.gregorianToFixed(year, month, 1) + 1; return [year, month, day]; } static jalaliToFixed(year, month, day) { let newYear = PERSIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((8 * year + 21) / 33); if (NON_LEAP_CORRECTION.includes(year - 1)) { newYear -= 1; } return ( newYear - 1 + ((month <= 7) ? 31 * (month - 1) : 30 * (month - 1) + 6) + day ); } static fixedToJalali(fixedDate) { const daysSinceEpoch = fixedDate - Converter.jalaliToFixed(1, 1, 1); let year = 1 + Math.floor((33 * daysSinceEpoch + 3) / PERSIAN_CYCLE_DAYS); let dayOfYear = fixedDate - Converter.jalaliToFixed(year, 1, 1) + 1; if (dayOfYear === 366 && NON_LEAP_CORRECTION.includes(year)) { year += 1; dayOfYear = 1; } const month = (dayOfYear <= 186) ? divCeil(dayOfYear, 31) : divCeil(dayOfYear - 6, 30); const day = fixedDate - Converter.jalaliToFixed(year, month, 1) + 1; return [year, month, day]; } static leapPersian(jdate) { if (NON_LEAP_CORRECTION.includes(jdate)) { return false; } if (NON_LEAP_CORRECTION.includes(jdate - 1)) { return true; } return (25 * jdate + 11) % 33 < 8; } static leapGregorian(year) { return (year % 4 === 0 && ![100, 200, 300].includes(year % 400)); } }