UNPKG

@phensley/cldr-core

Version:
389 lines 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var cldr_schema_1 = require("@phensley/cldr-schema"); var fields_1 = require("./fields"); var timezone_1 = require("./timezone"); var numbering_1 = require("../numbering"); var zeropad = function (n, w) { return numbering_1.INTERNAL_NUMBERING.formatString(n, false, w); }; /** * Implementation order, based on calendar preference data and ease of implementation. * https://github.com/unicode-cldr/cldr-core/blob/master/supplemental/calendarPreferenceData.json * * Complete: * gregorian - widely used worldwide * persian - primary in AF, IR * japanese - secondary in JP, based on gregorian * iso8601 - based on gregorian * buddhist - primary in TH * * Next: * islamic-umalqura - primary in SA * chinese - secondary in CN, CX, HK, MO, SG, TW * islamic - secondary in many locales * dangi - secondary in KO, based on chinese * * Rest TBD * * Calendar calculations are compatible with those in the Unicode ICU project. */ // Indicates a null field to support computing on demand var NULL = Number.MAX_SAFE_INTEGER; var floor = Math.floor; var differenceFields = [ [4 /* YEAR */, cldr_schema_1.DateTimePatternField.YEAR], [7 /* MONTH */, cldr_schema_1.DateTimePatternField.MONTH], [10 /* DAY_OF_MONTH */, cldr_schema_1.DateTimePatternField.DAY], [14 /* AM_PM */, cldr_schema_1.DateTimePatternField.DAYPERIOD], [16 /* HOUR */, cldr_schema_1.DateTimePatternField.HOUR], [17 /* MINUTE */, cldr_schema_1.DateTimePatternField.MINUTE], ]; /** * Base class for dates in supported calendars. * * @alpha */ var CalendarDate = /** @class */ (function () { /** * Minimal fields required to construct any calendar date. */ function CalendarDate(_type, _firstDay, _minDays) { this._type = _type; this._firstDay = _firstDay; this._minDays = _minDays; this._fields = fields_1.dateFields(); // Compute week fields on demand. this._fields[6 /* WEEK_OF_YEAR */] = NULL; this._fields[5 /* YEAR_WOY */] = NULL; } CalendarDate.prototype.type = function () { return this._type; }; /** * Unix epoch with no timezone offset. */ CalendarDate.prototype.unixEpoch = function () { return this._fields[0 /* LOCAL_MILLIS */] + this._zoneInfo.offset; }; CalendarDate.prototype.firstDayOfWeek = function () { return this._firstDay; }; CalendarDate.prototype.minDaysInFirstWeek = function () { return this._minDays; }; /** * Returns a floating point number representing the real Julian Day, UTC. */ CalendarDate.prototype.julianDay = function () { var ms = (this._fields[13 /* MILLIS_IN_DAY */] + this._zoneInfo.offset) / 86400000 /* ONE_DAY_MS */; return (this._fields[1 /* JULIAN_DAY */] - 0.5) + ms; }; /** * CLDR's modified Julian day used as the basis for all date calculations. */ CalendarDate.prototype.modifiedJulianDay = function () { return this._fields[1 /* JULIAN_DAY */]; }; CalendarDate.prototype.era = function () { return this._fields[2 /* ERA */]; }; CalendarDate.prototype.extendedYear = function () { return this._fields[3 /* EXTENDED_YEAR */]; }; CalendarDate.prototype.year = function () { return this._fields[4 /* YEAR */]; }; CalendarDate.prototype.relatedYear = function () { return this._fields[3 /* EXTENDED_YEAR */]; }; CalendarDate.prototype.yearOfWeekOfYear = function () { this.computeWeekFields(); return this._fields[5 /* YEAR_WOY */]; }; CalendarDate.prototype.weekOfYear = function () { this.computeWeekFields(); return this._fields[6 /* WEEK_OF_YEAR */]; }; /** * Ordinal month, one-based, e.g. Gregorian JANUARY = 1. */ CalendarDate.prototype.month = function () { return this._fields[7 /* MONTH */]; }; /** * Returns the week of the month computed using the locale's 'first day * of week' and 'minimal days in first week' where applicable. * * For example, for the United States, weeks start on Sunday. * Saturday 9/1/2018 would be in week 1, and Sunday 9/2/2018 would * begin week 2. * * September * Su Mo Tu We Th Fr Sa * 1 * 2 3 4 5 6 7 8 * 9 10 11 12 13 14 15 * 16 17 18 19 20 21 22 * 23 24 25 26 27 28 29 * 30 */ CalendarDate.prototype.weekOfMonth = function () { this.computeWeekFields(); return this._fields[8 /* WEEK_OF_MONTH */]; }; CalendarDate.prototype.dayOfYear = function () { return this._fields[9 /* DAY_OF_YEAR */]; }; /** * Day of the week. 1 = SUNDAY, 2 = MONDAY, ..., 7 = SATURDAY */ CalendarDate.prototype.dayOfWeek = function () { return this._fields[11 /* DAY_OF_WEEK */]; }; /** * Ordinal day of the week. 1 if this is the 1st day of the week, * 2 if the 2nd, etc. Depends on the local starting day of the week. */ CalendarDate.prototype.ordinalDayOfWeek = function () { var weekday = this.dayOfWeek(); var firstDay = this.firstDayOfWeek(); return (7 - firstDay + weekday) % 7 + 1; }; /** * Ordinal number indicating the day of the week in the current month. * The result of this method can be used to format messages like * "2nd Sunday in August". */ CalendarDate.prototype.dayOfWeekInMonth = function () { this.computeWeekFields(); return this._fields[12 /* DAY_OF_WEEK_IN_MONTH */]; }; CalendarDate.prototype.dayOfMonth = function () { return this._fields[10 /* DAY_OF_MONTH */]; }; CalendarDate.prototype.isAM = function () { return this._fields[14 /* AM_PM */] === 0; }; /** * Indicates the hour of the morning or afternoon, used for the 12-hour * clock (0 - 11). Noon and midnight are 0, not 12. */ CalendarDate.prototype.hour = function () { return this._fields[16 /* HOUR */]; }; /** * Indicates the hour of the day, used for the 24-hour clock (0 - 23). * Noon is 12 and midnight is 0. */ CalendarDate.prototype.hourOfDay = function () { return this._fields[15 /* HOUR_OF_DAY */]; }; /** * Indicates the minute of the hour (0 - 59). */ CalendarDate.prototype.minute = function () { return this._fields[17 /* MINUTE */]; }; /** * Indicates the second of the minute (0 - 59). */ CalendarDate.prototype.second = function () { return this._fields[18 /* SECOND */]; }; CalendarDate.prototype.milliseconds = function () { return this._fields[19 /* MILLIS */]; }; CalendarDate.prototype.millisecondsInDay = function () { return this._fields[13 /* MILLIS_IN_DAY */]; }; CalendarDate.prototype.metaZoneId = function () { return this._zoneInfo.metaZoneId; }; CalendarDate.prototype.timeZoneId = function () { return this._zoneInfo.timeZoneId; }; CalendarDate.prototype.timeZoneOffset = function () { return this._zoneInfo.offset; }; CalendarDate.prototype.isLeapYear = function () { return this._fields[21 /* IS_LEAP */] === 1; }; CalendarDate.prototype.isDaylightSavings = function () { return this._zoneInfo.dst; }; /** * Computes the field of greatest difference between the two dates. * Note: This assumes the dates are of the same type and have the same * timezone offset. */ CalendarDate.prototype.fieldOfGreatestDifference = function (other) { var a = this._fields; var b = other._fields; for (var _i = 0, differenceFields_1 = differenceFields; _i < differenceFields_1.length; _i++) { var pair = differenceFields_1[_i]; var key = pair[0], field = pair[1]; if (a[key] !== b[key]) { return field; } } return cldr_schema_1.DateTimePatternField.SECOND; }; /** * Compute a new Julian day and milliseconds UTC by updating one or more fields. */ CalendarDate.prototype._add = function (fields) { // All day calculations will be relative to the current day of the month. var dom = this._fields[10 /* DAY_OF_MONTH */] + (fields.day || 0) + ((fields.week || 0) * 7); // Adjust the extended year and month. // TODO: move month overflow into monthStart() var month = (this._fields[7 /* MONTH */] - 1) + (fields.month || 0); var yadd = floor(month / 12); var year = this._fields[3 /* EXTENDED_YEAR */] + (fields.year || 0) + yadd; month -= yadd * 12; // Calculate days and milliseconds from the time-oriented fields. var _a = this._addTime(fields), days = _a[0], ms = _a[1]; // Calculate the Julian day for the adjusted year/month then add back the days. var jd = this.monthStart(year, month, false) + dom + days; return [jd, ms]; }; /** * Converts all time fields into [days, milliseconds]. */ CalendarDate.prototype._addTime = function (fields) { // Calculate the time difference in days and milliseconds var msDay = this._fields[13 /* MILLIS_IN_DAY */] + this.timeZoneOffset(); msDay += ((fields.hour || 0) * 3600000 /* ONE_HOUR_MS */) + ((fields.minute || 0) * 60000 /* ONE_MINUTE_MS */) + ((fields.second || 0) * 1000 /* ONE_SECOND_MS */) + ((fields.millis || 0)); var oneDay = 86400000 /* ONE_DAY_MS */; var days = floor(msDay / oneDay); var ms = msDay - (days * oneDay); return [days, ms]; }; CalendarDate.prototype.initFromUnixEpoch = function (ms, zoneId) { if (zoneId === void 0) { zoneId = 'UTC'; } zoneId = timezone_1.substituteZoneAlias(zoneId); this._zoneInfo = timezone_1.zoneInfoCache.get(ms, zoneId); jdFromUnixEpoch(ms - this._zoneInfo.offset, this._fields); computeBaseFields(this._fields); }; CalendarDate.prototype.initFromJD = function (jd, msDay, zoneId) { if (zoneId === void 0) { zoneId = 'UTC'; } var unixEpoch = unixEpochFromJD(jd, msDay); this.initFromUnixEpoch(unixEpoch, zoneId); }; CalendarDate.prototype._toString = function (type, year) { return type + " " + (year || this.year()) + "-" + zeropad(this.month(), 2) + "-" + zeropad(this.dayOfMonth(), 2) + " " + (zeropad(this.hourOfDay(), 2) + ":" + zeropad(this.minute(), 2) + ":" + zeropad(this.second(), 2)) + ("." + zeropad(this.milliseconds(), 3) + " " + this._zoneInfo.timeZoneId); }; /** * Compute WEEK_OF_YEAR and YEAR_WOY on demand. */ CalendarDate.prototype.computeWeekFields = function () { var f = this._fields; if (f[5 /* YEAR_WOY */] !== NULL) { return; } var eyear = f[3 /* EXTENDED_YEAR */]; var dow = f[11 /* DAY_OF_WEEK */]; var dom = f[10 /* DAY_OF_MONTH */]; var doy = f[9 /* DAY_OF_YEAR */]; var ywoy = eyear; var rdow = (dow + 7 - this._firstDay) % 7; var rdowJan1 = (dow - doy + 7001 - this._firstDay) % 7; var woy = floor((doy - 1 + rdowJan1) / 7); if ((7 - rdowJan1) >= this._minDays) { woy++; } if (woy === 0) { var prevDay = doy + this.yearLength(eyear - 1); woy = this.weekNumber(prevDay, prevDay, dow); ywoy--; } else { var lastDoy = this.yearLength(eyear); if (doy >= (lastDoy - 5)) { var lastRdow = (rdow + lastDoy - doy) % 7; if (lastRdow < 0) { lastRdow += 7; } if (((6 - lastRdow) >= this._minDays) && ((doy + 7 - rdow) > lastDoy)) { woy = 1; ywoy++; } } } f[8 /* WEEK_OF_MONTH */] = this.weekNumber(dom, dom, dow); f[6 /* WEEK_OF_YEAR */] = woy; f[5 /* YEAR_WOY */] = ywoy; f[12 /* DAY_OF_WEEK_IN_MONTH */] = ((dom - 1) / 7 | 0) + 1; }; CalendarDate.prototype.yearLength = function (y) { return this.monthStart(y + 1, 0, false) - this.monthStart(y, 0, false); }; CalendarDate.prototype.weekNumber = function (desiredDay, dayOfPeriod, dayOfWeek) { var psow = (dayOfWeek - this._firstDay - dayOfPeriod + 1) % 7; if (psow < 0) { psow += 7; } var weekNo = floor((desiredDay + psow - 1) / 7); return ((7 - psow) >= this._minDays) ? weekNo + 1 : weekNo; }; return CalendarDate; }()); exports.CalendarDate = CalendarDate; /** * Compute Julian day from timezone-adjusted Unix epoch milliseconds. */ var jdFromUnixEpoch = function (ms, f) { var oneDayMS = 86400000 /* ONE_DAY_MS */; var days = floor(ms / oneDayMS); var jd = days + 2440588 /* JD_UNIX_EPOCH */; var msDay = ms - (days * oneDayMS); f[1 /* JULIAN_DAY */] = jd; f[13 /* MILLIS_IN_DAY */] = msDay; }; /** * Given a Julian day and local milliseconds (in UTC), return the Unix * epoch milliseconds UTC. */ var unixEpochFromJD = function (jd, msDay) { var days = jd - 2440588 /* JD_UNIX_EPOCH */; return (days * 86400000 /* ONE_DAY_MS */) + msDay; }; /** * Compute fields common to all calendars. Before calling this, we must * have the JULIAN_DAY and MILLIS_IN_DAY fields set. Every calculation * is relative to these. */ var computeBaseFields = function (f) { var jd = f[1 /* JULIAN_DAY */]; checkJDRange(jd); var msDay = f[13 /* MILLIS_IN_DAY */]; var ms = msDay + ((jd - 2440588 /* JD_UNIX_EPOCH */) * 86400000 /* ONE_DAY_MS */); f[0 /* LOCAL_MILLIS */] = ms; f[1 /* JULIAN_DAY */] = jd; f[13 /* MILLIS_IN_DAY */] = msDay; f[19 /* MILLIS */] = msDay % 1000; msDay = msDay / 1000 | 0; f[18 /* SECOND */] = msDay % 60; msDay = msDay / 60 | 0; f[17 /* MINUTE */] = msDay % 60; msDay = msDay / 60 | 0; f[15 /* HOUR_OF_DAY */] = msDay; f[14 /* AM_PM */] = msDay / 12 | 0; f[16 /* HOUR */] = msDay % 12; var dow = (jd + 2 /* MONDAY */) % 7; if (dow < 1 /* SUNDAY */) { dow += 7; } f[11 /* DAY_OF_WEEK */] = dow; }; var checkJDRange = function (jd) { if (jd < 0 /* JD_MIN */ || jd > 4881503 /* JD_MAX */) { throw new Error("Julian day " + jd + " is outside the supported range of this library: " + ("Mon Jan 1 4713 B.C." /* JD_MIN */ + " to " + "Fri Dec 31 8652 A.D." /* JD_MAX */)); } }; //# sourceMappingURL=calendar.js.map