UNPKG

luxon

Version:
146 lines (120 loc) 4.05 kB
import { numberBetween, isLeapYear, timeObject, daysInYear, daysInMonth, weeksInWeekYear, isNumber } from './util'; const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]; function dayOfWeek(year, month, day) { const js = new Date(Date.UTC(year, month - 1, day)).getUTCDay(); return js === 0 ? 7 : js; } function computeOrdinal(year, month, day) { return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1]; } function uncomputeOrdinal(year, ordinal) { const table = isLeapYear(year) ? leapLadder : nonLeapLadder, month0 = table.findIndex(i => i < ordinal), day = ordinal - table[month0]; return { month: month0 + 1, day }; } /** * @private */ export function gregorianToWeek(gregObj) { const { year, month, day } = gregObj, ordinal = computeOrdinal(year, month, day), weekday = dayOfWeek(year, month, day); let weekNumber = Math.floor((ordinal - weekday + 10) / 7), weekYear; if (weekNumber < 1) { weekYear = year - 1; weekNumber = weeksInWeekYear(weekYear); } else if (weekNumber > weeksInWeekYear(year)) { weekYear = year + 1; weekNumber = 1; } else { weekYear = year; } return Object.assign({ weekYear, weekNumber, weekday }, timeObject(gregObj)); } export function weekToGregorian(weekData) { const { weekYear, weekNumber, weekday } = weekData, weekdayOfJan4 = dayOfWeek(weekYear, 1, 4), yearInDays = daysInYear(weekYear); let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 3, year; if (ordinal < 1) { year = weekYear - 1; ordinal += daysInYear(year); } else if (ordinal > yearInDays) { year = weekYear + 1; ordinal -= daysInYear(year); } else { year = weekYear; } const { month, day } = uncomputeOrdinal(year, ordinal); return Object.assign({ year, month, day }, timeObject(weekData)); } export function gregorianToOrdinal(gregData) { const { year, month, day } = gregData, ordinal = computeOrdinal(year, month, day); return Object.assign({ year, ordinal }, timeObject(gregData)); } export function ordinalToGregorian(ordinalData) { const { year, ordinal } = ordinalData, { month, day } = uncomputeOrdinal(year, ordinal); return Object.assign({ year, month, day }, timeObject(ordinalData)); } export function hasInvalidWeekData(obj) { const validYear = isNumber(obj.weekYear), validWeek = numberBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear)), validWeekday = numberBetween(obj.weekday, 1, 7); if (!validYear) { return 'weekYear out of range'; } else if (!validWeek) { return 'week out of range'; } else if (!validWeekday) { return 'weekday out of range'; } else return false; } export function hasInvalidOrdinalData(obj) { const validYear = isNumber(obj.year), validOrdinal = numberBetween(obj.ordinal, 1, daysInYear(obj.year)); if (!validYear) { return 'year out of range'; } else if (!validOrdinal) { return 'ordinal out of range'; } else return false; } export function hasInvalidGregorianData(obj) { const validYear = isNumber(obj.year), validMonth = numberBetween(obj.month, 1, 12), validDay = numberBetween(obj.day, 1, daysInMonth(obj.year, obj.month)); if (!validYear) { return 'year out of range'; } else if (!validMonth) { return 'month out of range'; } else if (!validDay) { return 'day out of range'; } else return false; } export function hasInvalidTimeData(obj) { const validHour = numberBetween(obj.hour, 0, 23), validMinute = numberBetween(obj.minute, 0, 59), validSecond = numberBetween(obj.second, 0, 59), validMillisecond = numberBetween(obj.millisecond, 0, 999); if (!validHour) { return 'hour out of range'; } else if (!validMinute) { return 'minute out of range'; } else if (!validSecond) { return 'second out of range'; } else if (!validMillisecond) { return 'millisecond out of range'; } else return false; }