UNPKG

timezonecomplete

Version:

DateTime, TimeZone, Duration and Period library aimed at providing a consistent and complete date-time interface, away from the original JavaScript Date class.

1,130 lines (1,128 loc) 959 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tc = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ /** * Copyright(c) 2016 ABB Switzerland Ltd. */ "use strict"; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); var error_1 = require("./error"); /** * Throws an Assertion error if the given condition is falsy * @param condition * @param name error name * @param format error message with percent-style placeholders * @param args arguments for error message format string * @throws [name] if `condition` is falsy */ function assert(condition, name, format) { var args = []; for (var _i = 3; _i < arguments.length; _i++) { args[_i - 3] = arguments[_i]; } if (!condition) { error_1.throwError.apply(void 0, __spreadArray([name, format], args, false)); } } exports.default = assert; },{"./error":5}],2:[function(require,module,exports){ /** * Copyright(c) 2014 ABB Switzerland Ltd. * * Olsen Timezone Database container */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.binaryInsertionIndex = exports.TimeStruct = exports.secondOfDay = exports.weekDayNoLeapSecs = exports.timeToUnixNoLeapSecs = exports.unixToTimeNoLeapSecs = exports.weekNumber = exports.weekDayInstanceInMonth = exports.calendarWeekInMonth = exports.weekOfMonth = exports.weekDayOnOrBefore = exports.weekDayOnOrAfter = exports.nthWeekDayOfMonth = exports.firstWeekDayOfMonth = exports.lastWeekDayOfMonth = exports.dayOfYear = exports.daysInMonth = exports.daysInYear = exports.isLeapYear = exports.stringToTimeUnit = exports.timeUnitToString = exports.timeUnitToMilliseconds = exports.TimeUnit = exports.WeekDay = void 0; var assert_1 = require("./assert"); var error_1 = require("./error"); var javascript_1 = require("./javascript"); var math = require("./math"); var strings = require("./strings"); /** * Day-of-week. Note the enum values correspond to JavaScript day-of-week: * Sunday = 0, Monday = 1 etc */ var WeekDay; (function (WeekDay) { WeekDay[WeekDay["Sunday"] = 0] = "Sunday"; WeekDay[WeekDay["Monday"] = 1] = "Monday"; WeekDay[WeekDay["Tuesday"] = 2] = "Tuesday"; WeekDay[WeekDay["Wednesday"] = 3] = "Wednesday"; WeekDay[WeekDay["Thursday"] = 4] = "Thursday"; WeekDay[WeekDay["Friday"] = 5] = "Friday"; WeekDay[WeekDay["Saturday"] = 6] = "Saturday"; })(WeekDay || (exports.WeekDay = WeekDay = {})); /** * Time units */ var TimeUnit; (function (TimeUnit) { TimeUnit[TimeUnit["Millisecond"] = 0] = "Millisecond"; TimeUnit[TimeUnit["Second"] = 1] = "Second"; TimeUnit[TimeUnit["Minute"] = 2] = "Minute"; TimeUnit[TimeUnit["Hour"] = 3] = "Hour"; TimeUnit[TimeUnit["Day"] = 4] = "Day"; TimeUnit[TimeUnit["Week"] = 5] = "Week"; TimeUnit[TimeUnit["Month"] = 6] = "Month"; TimeUnit[TimeUnit["Year"] = 7] = "Year"; /** * End-of-enum marker, do not use */ TimeUnit[TimeUnit["MAX"] = 8] = "MAX"; })(TimeUnit || (exports.TimeUnit = TimeUnit = {})); /** * Approximate number of milliseconds for a time unit. * A day is assumed to have 24 hours, a month is assumed to equal 30 days * and a year is set to 360 days (because 12 months of 30 days). * * @param unit Time unit e.g. TimeUnit.Month * @returns The number of milliseconds. * @throws timezonecomplete.Argument.Unit for invalid unit */ function timeUnitToMilliseconds(unit) { switch (unit) { case TimeUnit.Millisecond: return 1; case TimeUnit.Second: return 1000; case TimeUnit.Minute: return 60 * 1000; case TimeUnit.Hour: return 60 * 60 * 1000; case TimeUnit.Day: return 86400000; case TimeUnit.Week: return 7 * 86400000; case TimeUnit.Month: return 30 * 86400000; case TimeUnit.Year: return 12 * 30 * 86400000; default: return (0, error_1.throwError)("Argument.Unit", "unknown time unit %d", unit); } } exports.timeUnitToMilliseconds = timeUnitToMilliseconds; /** * Time unit to lowercase string. If amount is specified, then the string is put in plural form * if necessary. * @param unit The unit * @param amount If this is unequal to -1 and 1, then the result is pluralized * @throws timezonecomplete.Argument.Unit for invalid time unit */ function timeUnitToString(unit, amount) { if (amount === void 0) { amount = 1; } if (!Number.isInteger(unit) || unit < 0 || unit >= TimeUnit.MAX) { return (0, error_1.throwError)("Argument.Unit", "invalid time unit %d", unit); } var result = TimeUnit[unit].toLowerCase(); if (amount === 1 || amount === -1) { return result; } else { return result + "s"; } } exports.timeUnitToString = timeUnitToString; /** * Convert a string to a numeric TimeUnit. Case-insensitive; time units can be singular or plural. * @param s * @throws timezonecomplete.Argument.S for invalid string */ function stringToTimeUnit(s) { var trimmed = s.trim().toLowerCase(); for (var i = 0; i < TimeUnit.MAX; ++i) { var other = timeUnitToString(i, 1); if (other === trimmed || (other + "s") === trimmed) { return i; } } return (0, error_1.throwError)("Argument.S", "Unknown time unit string '%s'", s); } exports.stringToTimeUnit = stringToTimeUnit; /** * @return True iff the given year is a leap year. * @throws timezonecomplete.Argument.Year if year is not integer */ function isLeapYear(year) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Invalid year %d", year); // from Wikipedia: // if year is not divisible by 4 then common year // else if year is not divisible by 100 then leap year // else if year is not divisible by 400 then common year // else leap year if (year % 4 !== 0) { return false; } else if (year % 100 !== 0) { return true; } else if (year % 400 !== 0) { return false; } else { return true; } } exports.isLeapYear = isLeapYear; /** * The days in a given year * @throws timezonecomplete.Argument.Year if year is not integer */ function daysInYear(year) { // rely on validation by isLeapYear return (isLeapYear(year) ? 366 : 365); } exports.daysInYear = daysInYear; /** * @param year The full year * @param month The month 1-12 * @return The number of days in the given month * @throws timezonecomplete.Argument.Year if year is not integer * @throws timezonecomplete.Argument.Month for invalid month number */ function daysInMonth(year, month) { switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; case 2: return (isLeapYear(year) ? 29 : 28); case 4: case 6: case 9: case 11: return 30; default: return (0, error_1.throwError)("Argument.Month", "Invalid month: %d", month); } } exports.daysInMonth = daysInMonth; /** * Returns the day of the year of the given date [0..365]. January first is 0. * * @param year The year e.g. 1986 * @param month Month 1-12 * @param day Day of month 1-31 * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month */ function dayOfYear(year, month, day) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(day) && day >= 1 && day <= daysInMonth(year, month), "Argument.Day", "day out of range"); var yearDay = 0; for (var i = 1; i < month; i++) { yearDay += daysInMonth(year, i); } yearDay += (day - 1); return yearDay; } exports.dayOfYear = dayOfYear; /** * Returns the last instance of the given weekday in the given month * * @param year The year * @param month the month 1-12 * @param weekDay the desired week day 0-6 * @return the last occurrence of the week day in the month * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.WeekDay for invalid week day */ function lastWeekDayOfMonth(year, month, weekDay) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(weekDay) && weekDay >= 0 && weekDay <= 6, "Argument.WeekDay", "weekDay out of range: %d", weekDay); var endOfMonth = new TimeStruct({ year: year, month: month, day: daysInMonth(year, month) }); var endOfMonthWeekDay = weekDayNoLeapSecs(endOfMonth.unixMillis); var diff = weekDay - endOfMonthWeekDay; if (diff > 0) { diff -= 7; } return endOfMonth.components.day + diff; } exports.lastWeekDayOfMonth = lastWeekDayOfMonth; /** * Returns the first instance of the given weekday in the given month * * @param year The year * @param month the month 1-12 * @param weekDay the desired week day * @return the first occurrence of the week day in the month * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.WeekDay for invalid week day */ function firstWeekDayOfMonth(year, month, weekDay) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(weekDay) && weekDay >= 0 && weekDay <= 6, "Argument.WeekDay", "weekDay out of range: %d", weekDay); var beginOfMonth = new TimeStruct({ year: year, month: month, day: 1 }); var beginOfMonthWeekDay = weekDayNoLeapSecs(beginOfMonth.unixMillis); var diff = weekDay - beginOfMonthWeekDay; if (diff < 0) { diff += 7; } return beginOfMonth.components.day + diff; } exports.firstWeekDayOfMonth = firstWeekDayOfMonth; /** * Returns the nth instance of the given weekday in the given month; throws if not found * * @param year The year * @param month the month 1-12 * @param weekDay the desired week day * @param dayInstance the desired week day instance, n * @return the first occurrence of the week day in the month * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.WeekDay for invalid week day * @throws timezonecomplete.Arugment.DayInstance for invalid day instance (not 1-5) * @throws timezonecomplete.NotFound if the month has no such instance (i.e. 5th instance, where only 4 exist) */ function nthWeekDayOfMonth(year, month, weekDay, dayInstance) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(weekDay) && weekDay >= 0 && weekDay <= 6, "Argument.WeekDay", "weekDay out of range: %d", weekDay); (0, assert_1.default)(Number.isInteger(dayInstance) && dayInstance >= 1 && dayInstance <= 5, "Argument.DayInstance", "dayInstance out of range: %d", dayInstance); var beginOfMonth = new TimeStruct({ year: year, month: month, day: 1 }); var beginOfMonthWeekDay = weekDayNoLeapSecs(beginOfMonth.unixMillis); var diff = weekDay - beginOfMonthWeekDay; if (diff < 0) { diff += 7; } diff += (dayInstance - 1) * 7; (0, assert_1.default)(beginOfMonth.components.day + diff <= daysInMonth(year, month), "NotFound", "The given month has no such day"); return beginOfMonth.components.day + diff; } exports.nthWeekDayOfMonth = nthWeekDayOfMonth; /** * Returns the day-of-month that is on the given weekday and which is >= the given day; throws if not found * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month * @throws timezonecomplete.Argument.WeekDay for invalid week day * @throws timezonecomplete.NotFound if the month has no such day */ function weekDayOnOrAfter(year, month, day, weekDay) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(day) && day >= 1 && day <= daysInMonth(year, month), "Argument.Day", "day out of range"); (0, assert_1.default)(Number.isInteger(weekDay) && weekDay >= 0 && weekDay <= 6, "Argument.WeekDay", "weekDay out of range: %d", weekDay); var start = new TimeStruct({ year: year, month: month, day: day }); var startWeekDay = weekDayNoLeapSecs(start.unixMillis); var diff = weekDay - startWeekDay; if (diff < 0) { diff += 7; } (0, assert_1.default)(start.components.day + diff <= daysInMonth(year, month), "NotFound", "The given month has no such weekday"); return start.components.day + diff; } exports.weekDayOnOrAfter = weekDayOnOrAfter; /** * Returns the day-of-month that is on the given weekday and which is <= the given day. * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month * @throws timezonecomplete.Argument.WeekDay for invalid week day * @throws timezonecomplete.NotFound if the month has no such day */ function weekDayOnOrBefore(year, month, day, weekDay) { (0, assert_1.default)(Number.isInteger(year), "Argument.Year", "Year out of range: %d", year); (0, assert_1.default)(Number.isInteger(month) && month >= 1 && month <= 12, "Argument.Month", "Month out of range: %d", month); (0, assert_1.default)(Number.isInteger(day) && day >= 1 && day <= daysInMonth(year, month), "Argument.Day", "day out of range"); (0, assert_1.default)(Number.isInteger(weekDay) && weekDay >= 0 && weekDay <= 6, "Argument.WeekDay", "weekDay out of range: %d", weekDay); var start = new TimeStruct({ year: year, month: month, day: day }); var startWeekDay = weekDayNoLeapSecs(start.unixMillis); var diff = weekDay - startWeekDay; if (diff > 0) { diff -= 7; } (0, assert_1.default)(start.components.day + diff >= 1, "NotFound", "The given month has no such weekday"); return start.components.day + diff; } exports.weekDayOnOrBefore = weekDayOnOrBefore; /** * The week of this month. There is no official standard for this, but we assume the same rules for the weekNumber: * week 1 is the week that has the 4th day of the month in it * * @param year The year * @param month The month [1-12] * @param day The day [1-31] * @return Week number [1-5] * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month */ function weekOfMonth(year, month, day) { // rely on year/month validation in firstWeekDayOfMonth (0, assert_1.default)(Number.isInteger(day) && day >= 1 && day <= daysInMonth(year, month), "Argument.Day", "day out of range"); var firstThursday = firstWeekDayOfMonth(year, month, WeekDay.Thursday); var firstMonday = firstWeekDayOfMonth(year, month, WeekDay.Monday); // Corner case: check if we are in week 1 or last week of previous month if (day < firstMonday) { if (firstThursday < firstMonday) { // Week 1 return 1; } else { // Last week of previous month if (month > 1) { // Default case return weekOfMonth(year, month - 1, daysInMonth(year, month - 1)); } else { // January return weekOfMonth(year - 1, 12, 31); } } } var lastMonday = lastWeekDayOfMonth(year, month, WeekDay.Monday); var lastThursday = lastWeekDayOfMonth(year, month, WeekDay.Thursday); // Corner case: check if we are in last week or week 1 of previous month if (day >= lastMonday) { if (lastMonday > lastThursday) { // Week 1 of next month return 1; } } // Normal case var result = Math.floor((day - firstMonday) / 7) + 1; if (firstThursday < 4) { result += 1; } return result; } exports.weekOfMonth = weekOfMonth; /** * The week of this month, based on counting calendar weeks. Unlike weekOfMonth() the first day of the month is * always week 1, and no days count as the last week of the previous month. The week number returned can be from 1-6, * as a month can span up to 6 different weeks on the calendar. The first day of the week, i.e. when the week number * increases, is customizable, and defaults to Monday. * * @param year The year * @param month The month [1-12] * @param day The day [1-31] * @param weekStartDay The week day to use as the start of the week * @return Week number [1-6] * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month */ function calendarWeekInMonth(year, month, day, weekStartDay) { if (weekStartDay === void 0) { weekStartDay = WeekDay.Monday; } // rely on year/month validation in weekDayOnOrAfter (0, assert_1.default)(Number.isInteger(day) && day >= 1 && day <= daysInMonth(year, month), "Argument.Day", "day out of range"); var firstFullWeekStartDay = weekDayOnOrAfter(year, month, 1, weekStartDay); var result = Math.floor((day - firstFullWeekStartDay + 7) / 7); if (firstFullWeekStartDay > 1) { result++; } return result; } exports.calendarWeekInMonth = calendarWeekInMonth; /** * Returns the weekday instance number in the month for the given date * * @param year The year * @param month The month [1-12] * @param day The day [1-31] * @return Instance number [1-5] * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month */ function weekDayInstanceInMonth(year, month, day) { // rely on year/month validation in firstWeekDayOfMonth var weekDay = weekDayNoLeapSecs(new TimeStruct({ year: year, month: month, day: day }).unixMillis); var firstInstanceOfDay = firstWeekDayOfMonth(year, month, weekDay); var result = ((day - firstInstanceOfDay) / 7) + 1; return result; } exports.weekDayInstanceInMonth = weekDayInstanceInMonth; /** * Returns the day-of-year of the Monday of week 1 in the given year. * Note that the result may lie in the previous year, in which case it * will be (much) greater than 4 * @throws timezonecomplete.Argument.Year for invalid year (non-integer) */ function getWeekOneDayOfYear(year) { // relay on weekDayOnOrAfter for year validation // first monday of January, minus one because we want day-of-year var result = weekDayOnOrAfter(year, 1, 1, WeekDay.Monday) - 1; if (result > 3) { // greater than jan 4th result -= 7; if (result < 0) { result += exports.daysInYear(year - 1); } } return result; } /** * The ISO 8601 week number for the given date. Week 1 is the week * that has January 4th in it, and it starts on Monday. * See https://en.wikipedia.org/wiki/ISO_week_date * * @param year Year e.g. 1988 * @param month Month 1-12 * @param day Day of month 1-31 * @return Week number 1-53 * @throws timezonecomplete.Argument.Year for invalid year (non-integer) * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month */ function weekNumber(year, month, day) { var doy = dayOfYear(year, month, day); // check end-of-year corner case: may be week 1 of next year if (doy >= dayOfYear(year, 12, 29)) { var nextYearWeekOne = getWeekOneDayOfYear(year + 1); if (nextYearWeekOne > 4 && nextYearWeekOne <= doy) { return 1; } } // check beginning-of-year corner case var thisYearWeekOne = getWeekOneDayOfYear(year); if (thisYearWeekOne > 4) { // week 1 is at end of last year var weekTwo = thisYearWeekOne + 7 - daysInYear(year - 1); if (doy < weekTwo) { return 1; } else { return Math.floor((doy - weekTwo) / 7) + 2; } } // Week 1 is entirely inside this year. if (doy < thisYearWeekOne) { // The date is part of the last week of prev year. return weekNumber(year - 1, 12, 31); } // normal cases; note that week numbers start from 1 so +1 return Math.floor((doy - thisYearWeekOne) / 7) + 1; } exports.weekNumber = weekNumber; /** * Convert a unix milli timestamp into a TimeT structure. * This does NOT take leap seconds into account. * @throws timezonecomplete.Argument.UnixMillis for non-integer `unixMillis` parameter */ function unixToTimeNoLeapSecs(unixMillis) { (0, assert_1.default)(Number.isInteger(unixMillis), "Argument.UnixMillis", "unixMillis should be an integer number"); var temp = unixMillis; var result = { year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0, milli: 0 }; var year; var month; if (unixMillis >= 0) { result.milli = math.positiveModulo(temp, 1000); temp = Math.floor(temp / 1000); result.second = math.positiveModulo(temp, 60); temp = Math.floor(temp / 60); result.minute = math.positiveModulo(temp, 60); temp = Math.floor(temp / 60); result.hour = math.positiveModulo(temp, 24); temp = Math.floor(temp / 24); year = 1970; while (temp >= daysInYear(year)) { temp -= daysInYear(year); year++; } result.year = year; month = 1; while (temp >= daysInMonth(year, month)) { temp -= daysInMonth(year, month); month++; } result.month = month; result.day = temp + 1; } else { // Note that a negative number modulo something yields a negative number. // We make it positive by adding the modulo. result.milli = math.positiveModulo(temp, 1000); temp = Math.floor(temp / 1000); result.second = math.positiveModulo(temp, 60); temp = Math.floor(temp / 60); result.minute = math.positiveModulo(temp, 60); temp = Math.floor(temp / 60); result.hour = math.positiveModulo(temp, 24); temp = Math.floor(temp / 24); year = 1969; while (temp < -daysInYear(year)) { temp += daysInYear(year); year--; } result.year = year; month = 12; while (temp < -daysInMonth(year, month)) { temp += daysInMonth(year, month); month--; } result.month = month; result.day = temp + 1 + daysInMonth(year, month); } return result; } exports.unixToTimeNoLeapSecs = unixToTimeNoLeapSecs; /** * Fill you any missing time component parts, defaults are 1970-01-01T00:00:00.000 * @throws timezonecomplete.Argument.Year for invalid year * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month * @throws timezonecomplete.Argument.Hour for invalid hour * @throws timezonecomplete.Argument.Minute for invalid minute * @throws timezonecomplete.Argument.Second for invalid second * @throws timezonecomplete.Argument.Milli for invalid milliseconds */ function normalizeTimeComponents(components) { var input = { year: typeof components.year === "number" ? components.year : 1970, month: typeof components.month === "number" ? components.month : 1, day: typeof components.day === "number" ? components.day : 1, hour: typeof components.hour === "number" ? components.hour : 0, minute: typeof components.minute === "number" ? components.minute : 0, second: typeof components.second === "number" ? components.second : 0, milli: typeof components.milli === "number" ? components.milli : 0, }; (0, assert_1.default)(Number.isInteger(input.year), "Argument.Year", "invalid year %d", input.year); (0, assert_1.default)(Number.isInteger(input.month) && input.month >= 1 && input.month <= 12, "Argument.Month", "invalid month %d", input.month); (0, assert_1.default)(Number.isInteger(input.day) && input.day >= 1 && input.day <= daysInMonth(input.year, input.month), "Argument.Day", "invalid day %d", input.day); (0, assert_1.default)(Number.isInteger(input.hour) && input.hour >= 0 && input.hour <= 23, "Argument.Hour", "invalid hour %d", input.hour); (0, assert_1.default)(Number.isInteger(input.minute) && input.minute >= 0 && input.minute <= 59, "Argument.Minute", "invalid minute %d", input.minute); (0, assert_1.default)(Number.isInteger(input.second) && input.second >= 0 && input.second <= 59, "Argument.Second", "invalid second %d", input.second); (0, assert_1.default)(Number.isInteger(input.milli) && input.milli >= 0 && input.milli <= 999, "Argument.Milli", "invalid milli %d", input.milli); return input; } function timeToUnixNoLeapSecs(a, month, day, hour, minute, second, milli) { var components = (typeof a === "number" ? { year: a, month: month, day: day, hour: hour, minute: minute, second: second, milli: milli } : a); var input = normalizeTimeComponents(components); return input.milli + 1000 * (input.second + input.minute * 60 + input.hour * 3600 + dayOfYear(input.year, input.month, input.day) * 86400 + (input.year - 1970) * 31536000 + Math.floor((input.year - 1969) / 4) * 86400 - Math.floor((input.year - 1901) / 100) * 86400 + Math.floor((input.year - 1900 + 299) / 400) * 86400); } exports.timeToUnixNoLeapSecs = timeToUnixNoLeapSecs; /** * Return the day-of-week. * This does NOT take leap seconds into account. * @throws timezonecomplete.Argument.UnixMillis for invalid `unixMillis` argument */ function weekDayNoLeapSecs(unixMillis) { (0, assert_1.default)(Number.isInteger(unixMillis), "Argument.UnixMillis", "unixMillis should be an integer number"); var epochDay = WeekDay.Thursday; var days = Math.floor(unixMillis / 1000 / 86400); return math.positiveModulo(epochDay + days, 7); } exports.weekDayNoLeapSecs = weekDayNoLeapSecs; /** * N-th second in the day, counting from 0 * @throws timezonecomplete.Argument.Hour for invalid hour * @throws timezonecomplete.Argument.Minute for invalid minute * @throws timezonecomplete.Argument.Second for invalid second */ function secondOfDay(hour, minute, second) { (0, assert_1.default)(Number.isInteger(hour) && hour >= 0 && hour <= 23, "Argument.Hour", "invalid hour %d", hour); (0, assert_1.default)(Number.isInteger(minute) && minute >= 0 && minute <= 59, "Argument.Minute", "invalid minute %d", minute); (0, assert_1.default)(Number.isInteger(second) && second >= 0 && second <= 61, "Argument.Second", "invalid second %d", second); return (((hour * 60) + minute) * 60) + second; } exports.secondOfDay = secondOfDay; /** * Basic representation of a date and time */ var TimeStruct = /** @class */ (function () { /** * Constructor implementation */ function TimeStruct(a) { if (typeof a === "number") { (0, assert_1.default)(Number.isInteger(a), "Argument.UnixMillis", "invalid unix millis %d", a); this._unixMillis = a; } else { (0, assert_1.default)(typeof a === "object" && a !== null, "Argument.Components", "invalid components object"); this._components = normalizeTimeComponents(a); } } /** * Returns a TimeStruct from the given year, month, day etc * * @param year Year e.g. 1970 * @param month Month 1-12 * @param day Day 1-31 * @param hour Hour 0-23 * @param minute Minute 0-59 * @param second Second 0-59 (no leap seconds) * @param milli Millisecond 0-999 * @throws timezonecomplete.Argument.Year for invalid year * @throws timezonecomplete.Argument.Month for invalid month * @throws timezonecomplete.Argument.Day for invalid day of month * @throws timezonecomplete.Argument.Hour for invalid hour * @throws timezonecomplete.Argument.Minute for invalid minute * @throws timezonecomplete.Argument.Second for invalid second * @throws timezonecomplete.Argument.Milli for invalid milliseconds */ TimeStruct.fromComponents = function (year, month, day, hour, minute, second, milli) { return new TimeStruct({ year: year, month: month, day: day, hour: hour, minute: minute, second: second, milli: milli }); }; /** * Create a TimeStruct from a number of unix milliseconds * (backward compatibility) * @throws timezonecomplete.Argument.UnixMillis for non-integer milliseconds */ TimeStruct.fromUnix = function (unixMillis) { return new TimeStruct(unixMillis); }; /** * Create a TimeStruct from a JavaScript date * * @param d The date * @param df Which functions to take (getX() or getUTCX()) * @throws nothing */ TimeStruct.fromDate = function (d, df) { if (df === javascript_1.DateFunctions.Get) { return new TimeStruct({ year: d.getFullYear(), month: d.getMonth() + 1, day: d.getDate(), hour: d.getHours(), minute: d.getMinutes(), second: d.getSeconds(), milli: d.getMilliseconds() }); } else { return new TimeStruct({ year: d.getUTCFullYear(), month: d.getUTCMonth() + 1, day: d.getUTCDate(), hour: d.getUTCHours(), minute: d.getUTCMinutes(), second: d.getUTCSeconds(), milli: d.getUTCMilliseconds() }); } }; /** * Returns a TimeStruct from an ISO 8601 string WITHOUT time zone * @throws timezonecomplete.Argument.S if `s` is not a proper iso string */ TimeStruct.fromString = function (s) { try { var year = 1970; var month = 1; var day = 1; var hour = 0; var minute = 0; var second = 0; var fractionMillis = 0; var lastUnit = TimeUnit.Year; // separate any fractional part var split = s.trim().split("."); (0, assert_1.default)(split.length >= 1 && split.length <= 2, "Argument.S", "Empty string or multiple dots."); // parse main part var isBasicFormat = (s.indexOf("-") === -1); if (isBasicFormat) { (0, assert_1.default)(split[0].match(/^((\d)+)|(\d\d\d\d\d\d\d\dT(\d)+)$/), "Argument.S", "ISO string in basic notation may only contain numbers before the fractional part"); // remove any "T" separator split[0] = split[0].replace("T", ""); (0, assert_1.default)([4, 8, 10, 12, 14].indexOf(split[0].length) !== -1, "Argument.S", "Padding or required components are missing. Note that YYYYMM is not valid per ISO 8601"); if (split[0].length >= 4) { year = parseInt(split[0].substr(0, 4), 10); lastUnit = TimeUnit.Year; } if (split[0].length >= 8) { month = parseInt(split[0].substr(4, 2), 10); day = parseInt(split[0].substr(6, 2), 10); // note that YYYYMM format is disallowed so if month is present, day is too lastUnit = TimeUnit.Day; } if (split[0].length >= 10) { hour = parseInt(split[0].substr(8, 2), 10); lastUnit = TimeUnit.Hour; } if (split[0].length >= 12) { minute = parseInt(split[0].substr(10, 2), 10); lastUnit = TimeUnit.Minute; } if (split[0].length >= 14) { second = parseInt(split[0].substr(12, 2), 10); lastUnit = TimeUnit.Second; } } else { (0, assert_1.default)(split[0].match(/^\d\d\d\d(-\d\d-\d\d((T)?\d\d(\:\d\d(:\d\d)?)?)?)?$/), "Argument.S", "Invalid ISO string"); var dateAndTime = []; if (s.indexOf("T") !== -1) { dateAndTime = split[0].split("T"); } else if (s.length > 10) { dateAndTime = [split[0].substr(0, 10), split[0].substr(10)]; } else { dateAndTime = [split[0], ""]; } (0, assert_1.default)([4, 10].indexOf(dateAndTime[0].length) !== -1, "Argument.S", "Padding or required components are missing. Note that YYYYMM is not valid per ISO 8601"); if (dateAndTime[0].length >= 4) { year = parseInt(dateAndTime[0].substr(0, 4), 10); lastUnit = TimeUnit.Year; } if (dateAndTime[0].length >= 10) { month = parseInt(dateAndTime[0].substr(5, 2), 10); day = parseInt(dateAndTime[0].substr(8, 2), 10); // note that YYYYMM format is disallowed so if month is present, day is too lastUnit = TimeUnit.Day; } if (dateAndTime[1].length >= 2) { hour = parseInt(dateAndTime[1].substr(0, 2), 10); lastUnit = TimeUnit.Hour; } if (dateAndTime[1].length >= 5) { minute = parseInt(dateAndTime[1].substr(3, 2), 10); lastUnit = TimeUnit.Minute; } if (dateAndTime[1].length >= 8) { second = parseInt(dateAndTime[1].substr(6, 2), 10); lastUnit = TimeUnit.Second; } } // parse fractional part if (split.length > 1 && split[1].length > 0) { var fraction = parseFloat("0." + split[1]); switch (lastUnit) { case TimeUnit.Year: fractionMillis = daysInYear(year) * 86400000 * fraction; break; case TimeUnit.Day: fractionMillis = 86400000 * fraction; break; case TimeUnit.Hour: fractionMillis = 3600000 * fraction; break; case TimeUnit.Minute: fractionMillis = 60000 * fraction; break; case TimeUnit.Second: fractionMillis = 1000 * fraction; break; } } // combine main and fractional part year = math.roundSym(year); month = math.roundSym(month); day = math.roundSym(day); hour = math.roundSym(hour); minute = math.roundSym(minute); second = math.roundSym(second); var unixMillis = timeToUnixNoLeapSecs({ year: year, month: month, day: day, hour: hour, minute: minute, second: second }); unixMillis = math.roundSym(unixMillis + fractionMillis); return new TimeStruct(unixMillis); } catch (e) { if ((0, error_1.errorIs)(e, [ "Argument.S", "Argument.Year", "Argument.Month", "Argument.Day", "Argument.Hour", "Argument.Minute", "Argument.Second", "Argument.Milli" ])) { return (0, error_1.throwError)("Argument.S", "Invalid ISO 8601 string: \"%s\": %s", s, e.message); } else { throw e; // programming error } } }; Object.defineProperty(TimeStruct.prototype, "unixMillis", { get: function () { if (this._unixMillis === undefined) { this._unixMillis = timeToUnixNoLeapSecs(this._components); } return this._unixMillis; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "components", { get: function () { if (!this._components) { this._components = unixToTimeNoLeapSecs(this._unixMillis); } return this._components; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "year", { get: function () { return this.components.year; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "month", { get: function () { return this.components.month; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "day", { get: function () { return this.components.day; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "hour", { get: function () { return this.components.hour; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "minute", { get: function () { return this.components.minute; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "second", { get: function () { return this.components.second; }, enumerable: false, configurable: true }); Object.defineProperty(TimeStruct.prototype, "milli", { get: function () { return this.components.milli; }, enumerable: false, configurable: true }); /** * The day-of-year 0-365 * @throws nothing */ TimeStruct.prototype.yearDay = function () { return dayOfYear(this.components.year, this.components.month, this.components.day); }; /** * Equality function * @param other * @throws TypeError if other is not an Object */ TimeStruct.prototype.equals = function (other) { return this.valueOf() === other.valueOf(); }; /** * @throws nothing */ TimeStruct.prototype.valueOf = function () { return this.unixMillis; }; /** * @throws nothing */ TimeStruct.prototype.clone = function () { if (this._components) { return new TimeStruct(this._components); } else { return new TimeStruct(this._unixMillis); } }; /** * Validate a timestamp. Filters out non-existing values for all time components * @returns true iff the timestamp is valid * @throws nothing */ TimeStruct.prototype.validate = function () { if (this._components) { return this.components.month >= 1 && this.components.month <= 12 && this.components.day >= 1 && this.components.day <= daysInMonth(this.components.year, this.components.month) && this.components.hour >= 0 && this.components.hour <= 23 && this.components.minute >= 0 && this.components.minute <= 59 && this.components.second >= 0 && this.components.second <= 59 && this.components.milli >= 0 && this.components.milli <= 999; } else { return true; } }; /** * ISO 8601 string YYYY-MM-DDThh:mm:ss.nnn * @throws nothing */ TimeStruct.prototype.toString = function () { return strings.padLeft(this.components.year.toString(10), 4, "0") + "-" + strings.padLeft(this.components.month.toString(10), 2, "0") + "-" + strings.padLeft(this.components.day.toString(10), 2, "0") + "T" + strings.padLeft(this.components.hour.toString(10), 2, "0") + ":" + strings.padLeft(this.components.minute.toString(10), 2, "0") + ":" + strings.padLeft(this.components.second.toString(10), 2, "0") + "." + strings.padLeft(this.components.milli.toString(10), 3, "0"); }; return TimeStruct; }()); exports.TimeStruct = TimeStruct; /** * Binary search * @param array Array to search * @param compare Function that should return < 0 if given element is less than searched element etc * @returns The insertion index of the element to look for * @throws TypeError if arr is not an array * @throws whatever `compare()` throws */ function binaryInsertionIndex(arr, compare) { var minIndex = 0; var maxIndex = arr.length - 1; var currentIndex; var currentElement; // no array / empty array if (!arr) { return 0; } if (arr.length === 0) { return 0; } // out of bounds if (compare(arr[0]) > 0) { return 0; } if (compare(arr[maxIndex]) < 0) { return maxIndex + 1; } // element in range while (minIndex <= maxIndex) { currentIndex = Math.floor((minIndex + maxIndex) / 2); currentElement = arr[currentIndex]; if (compare(currentElement) < 0) { minIndex = currentIndex + 1; } else if (compare(currentElement) > 0) { maxIndex = currentIndex - 1; } else { return currentIndex; } } return maxIndex; } exports.binaryInsertionIndex = binaryInsertionIndex; },{"./assert":1,"./error":5,"./javascript":8,"./math":10,"./strings":13}],3:[function(require,module,exports){ /** * Copyright(c) 2014 ABB Switzerland Ltd. * * Date+time+timezone representation */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isDateTime = exports.DateTime = exports.now = exports.nowUtc = exports.nowLocal = void 0; var assert_1 = require("./assert"); var basics = require("./basics"); var basics_1 = require("./basics"); var duration_1 = require("./duration"); var error_1 = require("./error"); var format = require("./format"); var javascript_1 = require("./javascript"); var math = require("./math"); var parseFuncs = require("./parse"); var timesource_1 = require("./timesource"); var timezone_1 = require("./timezone"); var tz_database_1 = require("./tz-database"); /** * Current date+time in local time * @throws nothing */ function nowLocal() { return DateTime.nowLocal(); } exports.nowLocal = nowLocal; /** * Current date+time in UTC time * @throws timezonecomplete.NotFound.Zone if the UTC time zone doesn't exist in the time zone database */ function nowUtc() { return DateTime.nowUtc(); } exports.nowUtc = nowUtc; /** * Current date+time in the given time zone * @param timeZone The desired time zone (optional, defaults to UTC). * @throws timezonecomplete.NotFound.Zone if the UTC time zone doesn't exist in the time zone database */ function now(timeZone) { if (timeZone === void 0) { timeZone = timezone_1.TimeZone.utc(); } return DateTime.now(timeZone); } exports.now = now; /** * * @param localTime * @param fromZone * @throws nothing */ function convertToUtc(localTime, fromZone) { if (fromZone) { var offset = fromZone.offsetForZone(localTime); return new basics_1.TimeStruct(localTime.unixMillis - offset * 60000); } else { return localTime.clone(); } } /** * * @param utcTime * @param toZone * @throws nothing */ function convertFromUtc(utcTime, toZone) { /* istanbul ignore else */ if (toZone) { var offset = toZone.offsetForUtc(utcTime); return toZone.normalizeZoneTime(new basics_1.TimeStruct(utcTime.unixMillis + offset * 60000)); } else { return utcTime.clone(); } } /** * DateTime class which is time zone-aware * and which can be mocked for testing purposes. */ var DateTime = /** @class */ (function () { /** * Constructor implementation, @see overrides */ function DateTime(a1, a2, a3, h, m, s, ms, timeZone) { /** * Allow not using instanceof */ this.kind = "DateTime"; switch (typeof (a1)) { case "number": { if (typeof a2 !== "number") { (0, assert_1.default)(a3 === undefined && h === undefined && m === undefined && s === undefined && ms === undefined && timeZone === undefined, "Argument.A3", "for unix timestamp datetime constructor, third through 8th argument must be undefined"); (0, assert_1.default)(a2 === undefined || a2 === null || isTimeZone(a2), "Argument.TimeZone", "DateTime.DateTime(): second arg should be a TimeZone object."); // unix timestamp constructor this._zone = (typeof (a2) === "object" && isTimeZone(a2) ? a2 : undefined); var unixMillis = (0, error_1.convertError)("Argument.UnixMillis", function () { return math.roundSym(a1); }); if (this._zone) { this._zoneDate = this._zone.normalizeZoneTime(new basics_1.TimeStruct(unixMillis)); } else { this._zoneDate = new basics_1.TimeStruct(unixMillis); } } else { // year month day constructor (0, assert_1.default)(typeof (a2) === "number", "Argument.Year", "DateTime.DateTime(): Expect month to be a number."); (0, assert_1.default)(typeof (a3) === "number", "Argument.Month", "DateTime.DateTime(): Expect day to be a number."); (0, assert_1.default)(timeZone === undefined || timeZone === null || isTimeZone(timeZone), "Argument.TimeZone", "DateTime.DateTime(): eighth arg should be a TimeZone object."); var year_1 = a1; var month_1 = a2; var day_1 = a3; var hour_1 = (typeof (h) === "number" ? h : 0); var minute_1 = (typeof (m) === "number" ? m : 0); var second_1 = (typeof (s) === "number" ? s : 0); var milli_1 = (typeof (ms) === "number" ? ms : 0); year_1 = (0, error_1.convertError)("Argument.Year", function () { return math.roundSym(year_1); }); month_1 = (0, error_1.convertError)("Argument.Month", function () { return math.roundSym(month_1); }); day_1 = (0, error_1.convertError)("Argument.Day", function () { return math.roundSym(day_1); }); hour_1 = (0, error_1.convertError)("Ar