diff options
| author | Shipwreckt <me@shipwreckt.co.uk> | 2025-10-31 20:02:14 +0000 |
|---|---|---|
| committer | Shipwreckt <me@shipwreckt.co.uk> | 2025-10-31 20:02:14 +0000 |
| commit | 7a52ddeba2a68388b544f529d2d92104420f77b0 (patch) | |
| tree | 15ddd47457a2cb4a96060747437d36474e4f6b4e /node_modules/luxon/src/impl/conversions.js | |
| parent | 53d6ae2b5568437afa5e4995580a3fb679b7b91b (diff) | |
Changed from static to 11ty!
Diffstat (limited to 'node_modules/luxon/src/impl/conversions.js')
| -rw-r--r-- | node_modules/luxon/src/impl/conversions.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/node_modules/luxon/src/impl/conversions.js b/node_modules/luxon/src/impl/conversions.js new file mode 100644 index 0000000..4c7d117 --- /dev/null +++ b/node_modules/luxon/src/impl/conversions.js @@ -0,0 +1,206 @@ +import { + integerBetween, + isLeapYear, + timeObject, + daysInYear, + daysInMonth, + weeksInWeekYear, + isInteger, + isUndefined, +} from "./util.js"; +import Invalid from "./invalid.js"; +import { ConflictingSpecificationError } from "../errors.js"; + +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 unitOutOfRange(unit, value) { + return new Invalid( + "unit out of range", + `you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid` + ); +} + +export function dayOfWeek(year, month, day) { + const d = new Date(Date.UTC(year, month - 1, day)); + + if (year < 100 && year >= 0) { + d.setUTCFullYear(d.getUTCFullYear() - 1900); + } + + const js = d.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 }; +} + +export function isoWeekdayToLocal(isoWeekday, startOfWeek) { + return ((isoWeekday - startOfWeek + 7) % 7) + 1; +} + +/** + * @private + */ + +export function gregorianToWeek(gregObj, minDaysInFirstWeek = 4, startOfWeek = 1) { + const { year, month, day } = gregObj, + ordinal = computeOrdinal(year, month, day), + weekday = isoWeekdayToLocal(dayOfWeek(year, month, day), startOfWeek); + + let weekNumber = Math.floor((ordinal - weekday + 14 - minDaysInFirstWeek) / 7), + weekYear; + + if (weekNumber < 1) { + weekYear = year - 1; + weekNumber = weeksInWeekYear(weekYear, minDaysInFirstWeek, startOfWeek); + } else if (weekNumber > weeksInWeekYear(year, minDaysInFirstWeek, startOfWeek)) { + weekYear = year + 1; + weekNumber = 1; + } else { + weekYear = year; + } + + return { weekYear, weekNumber, weekday, ...timeObject(gregObj) }; +} + +export function weekToGregorian(weekData, minDaysInFirstWeek = 4, startOfWeek = 1) { + const { weekYear, weekNumber, weekday } = weekData, + weekdayOfJan4 = isoWeekdayToLocal(dayOfWeek(weekYear, 1, minDaysInFirstWeek), startOfWeek), + yearInDays = daysInYear(weekYear); + + let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 7 + minDaysInFirstWeek, + year; + + if (ordinal < 1) { + year = weekYear - 1; + ordinal += daysInYear(year); + } else if (ordinal > yearInDays) { + year = weekYear + 1; + ordinal -= daysInYear(weekYear); + } else { + year = weekYear; + } + + const { month, day } = uncomputeOrdinal(year, ordinal); + return { year, month, day, ...timeObject(weekData) }; +} + +export function gregorianToOrdinal(gregData) { + const { year, month, day } = gregData; + const ordinal = computeOrdinal(year, month, day); + return { year, ordinal, ...timeObject(gregData) }; +} + +export function ordinalToGregorian(ordinalData) { + const { year, ordinal } = ordinalData; + const { month, day } = uncomputeOrdinal(year, ordinal); + return { year, month, day, ...timeObject(ordinalData) }; +} + +/** + * Check if local week units like localWeekday are used in obj. + * If so, validates that they are not mixed with ISO week units and then copies them to the normal week unit properties. + * Modifies obj in-place! + * @param obj the object values + */ +export function usesLocalWeekValues(obj, loc) { + const hasLocaleWeekData = + !isUndefined(obj.localWeekday) || + !isUndefined(obj.localWeekNumber) || + !isUndefined(obj.localWeekYear); + if (hasLocaleWeekData) { + const hasIsoWeekData = + !isUndefined(obj.weekday) || !isUndefined(obj.weekNumber) || !isUndefined(obj.weekYear); + + if (hasIsoWeekData) { + throw new ConflictingSpecificationError( + "Cannot mix locale-based week fields with ISO-based week fields" + ); + } + if (!isUndefined(obj.localWeekday)) obj.weekday = obj.localWeekday; + if (!isUndefined(obj.localWeekNumber)) obj.weekNumber = obj.localWeekNumber; + if (!isUndefined(obj.localWeekYear)) obj.weekYear = obj.localWeekYear; + delete obj.localWeekday; + delete obj.localWeekNumber; + delete obj.localWeekYear; + return { + minDaysInFirstWeek: loc.getMinDaysInFirstWeek(), + startOfWeek: loc.getStartOfWeek(), + }; + } else { + return { minDaysInFirstWeek: 4, startOfWeek: 1 }; + } +} + +export function hasInvalidWeekData(obj, minDaysInFirstWeek = 4, startOfWeek = 1) { + const validYear = isInteger(obj.weekYear), + validWeek = integerBetween( + obj.weekNumber, + 1, + weeksInWeekYear(obj.weekYear, minDaysInFirstWeek, startOfWeek) + ), + validWeekday = integerBetween(obj.weekday, 1, 7); + + if (!validYear) { + return unitOutOfRange("weekYear", obj.weekYear); + } else if (!validWeek) { + return unitOutOfRange("week", obj.weekNumber); + } else if (!validWeekday) { + return unitOutOfRange("weekday", obj.weekday); + } else return false; +} + +export function hasInvalidOrdinalData(obj) { + const validYear = isInteger(obj.year), + validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validOrdinal) { + return unitOutOfRange("ordinal", obj.ordinal); + } else return false; +} + +export function hasInvalidGregorianData(obj) { + const validYear = isInteger(obj.year), + validMonth = integerBetween(obj.month, 1, 12), + validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month)); + + if (!validYear) { + return unitOutOfRange("year", obj.year); + } else if (!validMonth) { + return unitOutOfRange("month", obj.month); + } else if (!validDay) { + return unitOutOfRange("day", obj.day); + } else return false; +} + +export function hasInvalidTimeData(obj) { + const { hour, minute, second, millisecond } = obj; + const validHour = + integerBetween(hour, 0, 23) || + (hour === 24 && minute === 0 && second === 0 && millisecond === 0), + validMinute = integerBetween(minute, 0, 59), + validSecond = integerBetween(second, 0, 59), + validMillisecond = integerBetween(millisecond, 0, 999); + + if (!validHour) { + return unitOutOfRange("hour", hour); + } else if (!validMinute) { + return unitOutOfRange("minute", minute); + } else if (!validSecond) { + return unitOutOfRange("second", second); + } else if (!validMillisecond) { + return unitOutOfRange("millisecond", millisecond); + } else return false; +} |
