UNPKG

abushakir

Version:

Ethiopian Datetime and Calendar Reckoning system. COMPUTUS.

689 lines (688 loc) 24.9 kB
"use strict"; // Copyright 2012 (2020 GC) Nabute. All rights reserved. // Use of this source code is governed by MIT license, which can be found // in the LICENSE file. var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var constants_1 = require("../utils/constants"); var duration_1 = __importDefault(require("../utils/duration")); var polyfill_1 = require("@js-temporal/polyfill"); var EtDatetime = /** @class */ (function () { /** * Constructs an EtDatetime instance. * * @param args Either: * - No arguments → initializes to current time * - One number → milliseconds since Unix epoch OR Ethiopic year * - Multiple positional Ethiopic components: (year, month, day, hour?, minute?, second?, millisecond?) */ function EtDatetime() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (args.length >= 2) { this.fixed = this.fixedFromEthiopic(this.toNumber(args[0]), this.toNumber(args[1]), this.toNumber(args[2])); this.moment = this.dateToEpoch(this.toNumber(args[0]), this.toNumber(args[1]), this.toNumber(args[2]), this.toNumber(args[3]), this.toNumber(args[4]), this.toNumber(args[5]), this.toNumber(args[6])); if (this.fixed === null) throw new Error('ARGUMENT ERROR: Unacceptable argument.'); } if (args.length === 1) { var value = this.toNumber(args[0]); if (Math.abs(value) > 9999) { this.fromMillisecondsSinceEpoch(value); } else { this.fixed = this.fixedFromEthiopic(value, 1, 1); this.moment = this.dateToEpoch(value, 1, 1, 0, 0, 0, 0); if (this.fixed === null) throw new Error('ARGUMENT ERROR: Unacceptable argument.'); } } if (args.length === 0) { this.fixed = this.fixedFromUnix(Date.now()); this.moment = Date.now(); } if (!this.fixed) { this.fixed = 0; } } /** * Sets the current datetime using a Unix timestamp in milliseconds. * * @param millisecondsSinceEpoch Timestamp in milliseconds since the Unix epoch */ EtDatetime.prototype.fromMillisecondsSinceEpoch = function (millisecondsSinceEpoch) { this.moment = millisecondsSinceEpoch; this.fixed = this.fixedFromUnix(millisecondsSinceEpoch); if (this.fixed === null) throw new Error('ARGUMENT ERROR: Unacceptable argument.'); if (Math.abs(millisecondsSinceEpoch) >= constants_1.constants.maxMillisecondsSinceEpoch) throw new Error("Calendar outside valid range " + constants_1.constants.maxMillisecondsSinceEpoch); }; /** * Updates the EtDatetime to the current system time. */ EtDatetime.prototype.now = function () { this.fixed = this.fixedFromUnix(Date.now()); this.moment = Date.now(); }; Object.defineProperty(EtDatetime.prototype, "year", { /** Ethiopic year */ get: function () { return Math.floor((4 * (this.fixed - constants_1.constants._ethiopicEpoch) + 1463) / 1461); }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "month", { /** Ethiopic month (1-13) */ get: function () { return Math.floor((this.fixed - this.fixedFromEthiopic(this.year, 1, 1)) / 30) + 1; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "monthGeez", { /** Ethiopic month name in Geez */ get: function () { return constants_1.constants._months[(this.month - 1) % 13]; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "day", { /** Ethiopic day of the month (1-30) */ get: function () { return this.fixed + 1 - this.fixedFromEthiopic(this.year, this.month, 1); }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "dayGeez", { /** Day of the month in Geez numeral format */ get: function () { return constants_1.constants._dayNumbers[(this.day - 1) % 30]; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "hour", { /** Hour of the day (0-23) */ get: function () { return Math.floor(this.moment / constants_1.constants.hourMilliSec) % 24; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "minute", { /** Minute of the hour (0-59) */ get: function () { return Math.floor(this.moment / constants_1.constants.minMilliSec) % 60; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "second", { /** Second of the minute (0-59) */ get: function () { return Math.floor((this.moment / constants_1.constants.secMilliSec) % 60); }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "millisecond", { /** Millisecond of the second (0-999) */ get: function () { return this.moment % 1000; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "isLeap", { /** Whether this year is a leap year in the Ethiopian calendar */ get: function () { return this.year % 4 === 3; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "yearFirstDay", { /** The weekday index of the first day of the year (0-6, Sunday–Saturday) */ get: function () { return this._yearFirstDay(); }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "weekday", { /** Weekday index of the current date */ get: function () { return (this.yearFirstDay + (this.month - 1) * 2) % 7; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "date", { /** Date object: { year, month, day } */ get: function () { return { year: this.year, month: this.month, day: this.day }; }, enumerable: true, configurable: true }); Object.defineProperty(EtDatetime.prototype, "time", { /** Time object: { h, m, s } */ get: function () { return { h: this.hour, m: this.minute, s: this.second }; }, enumerable: true, configurable: true }); /** * Returns a formatted string representation: `yyyy-MM-ddTHH:mm:ss.sss` */ EtDatetime.prototype.toString = function () { return this.toIso8601String(); }; /** * Returns a formatted JSON-friendly object representation */ EtDatetime.prototype.toJson = function () { return { year: this.fourDigits(this.year), month: this.twoDigits(this.month), date: this.twoDigits(this.day), hour: this.twoDigits(this.hour), min: this.twoDigits(this.minute), sec: this.twoDigits(this.second), ms: this.threeDigits(this.millisecond), }; }; /** * Returns ISO-8601 formatted string. */ EtDatetime.prototype.toIso8601String = function () { var y = this.year >= -9999 && this.year <= 9999 ? this.fourDigits(this.year) : this.sixDigits(this.year); var m = this.twoDigits(this.month); var d = this.twoDigits(this.day); var h = this.twoDigits(this.hour); var min = this.twoDigits(this.minute); var sec = this.twoDigits(this.second); var ms = this.threeDigits(this.millisecond); return y + "-" + m + "-" + d + "T" + h + ":" + min + ":" + sec + "." + ms; }; /** * Returns true if this date is before the other. */ EtDatetime.prototype.isBefore = function (other) { return this.fixed < other.fixed || this.moment < other.moment; }; /** * Returns true if this date is after the other. */ EtDatetime.prototype.isAfter = function (other) { return this.fixed > other.fixed || this.moment > other.moment; }; /** * Returns true if this date is at the same moment as the other. */ EtDatetime.prototype.isAtSameMomentAs = function (other) { return this.fixed === other.fixed && this.moment === other.moment; }; /** * Compares this instance with another EtDatetime. * Returns -1 if earlier, 1 if later, or 0 if equal. */ EtDatetime.prototype.compareTo = function (other) { if (this.isBefore(other)) return -1; else if (this.isAtSameMomentAs(other)) return 0; else return 1; }; /** * Adds a Duration to this date. */ EtDatetime.prototype.add = function (duration) { return new EtDatetime(this.moment + duration.inMilliseconds); }; /** * Subtracts a Duration from this date. */ EtDatetime.prototype.subtract = function (duration) { return new EtDatetime(this.moment - duration.inMilliseconds); }; /** * Returns the Duration between this and another EtDatetime. */ EtDatetime.prototype.difference = function (other) { return new duration_1.default(Math.abs(this.fixed - other.fixed), 0, 0, 0, 0, 0); }; /** * Gets the fixed date from Ethiopic calendar date. */ EtDatetime.prototype.fixedFromEthiopic = function (year, month, day) { return Math.floor(constants_1.constants._ethiopicEpoch - 1 + 365 * (year - 1) + year / 4 + 30 * (month - 1) + day); }; /** * Gets the fixed date from Unix timestamp (in ms). */ EtDatetime.prototype.fixedFromUnix = function (ms) { return constants_1.constants._unixEpoch + Math.floor(ms / 86400000); }; /** * Converts Ethiopic date-time to Unix epoch milliseconds. */ EtDatetime.prototype.dateToEpoch = function (year, month, date, hour, minute, second, millisecond) { return ((this.fixedFromEthiopic(year, month, date) - constants_1.constants._unixEpoch) * constants_1.constants.dayMilliSec + (hour ? hour * constants_1.constants.hourMilliSec : 0) + (minute ? minute * constants_1.constants.minMilliSec : 0) + (second ? second * constants_1.constants.secMilliSec : 0) + (millisecond !== null && millisecond !== void 0 ? millisecond : 0)); }; /** * Returns the weekday of the first day of the year. */ EtDatetime.prototype._yearFirstDay = function () { var ameteAlem = constants_1.constants.ameteFida + this.year; var rabeet = Math.floor(ameteAlem / 4); return (ameteAlem + rabeet) % 7; }; /** Formats a year as 4-digit string (e.g., 2012) */ EtDatetime.prototype.fourDigits = function (n) { var abs = Math.abs(n); var sign = n < 0 ? '-' : ''; if (abs >= 1000) return "" + n; if (abs >= 100) return sign + "0" + abs; if (abs >= 10) return sign + "00" + abs; return sign + "000" + abs; }; /** Formats a year as 6-digit string (for extreme years) */ EtDatetime.prototype.sixDigits = function (n) { if (n < -9999 || n > 9999) throw new Error('Year out of scope'); var abs = Math.abs(n); var sign = n < 0 ? '-' : '+'; if (abs >= 100000) return "" + sign + abs; return sign + "0" + abs; }; /** Pads a number to 3 digits */ EtDatetime.prototype.threeDigits = function (n) { if (n >= 100) return "" + n; if (n >= 10) return "0" + n; return "00" + n; }; /** Pads a number to 2 digits */ EtDatetime.prototype.twoDigits = function (n) { return n >= 10 ? "" + n : "0" + n; }; /** * Converts various types to a number. * Throws if the type is invalid (symbol, object). */ EtDatetime.prototype.toNumber = function (value) { if (value === undefined) return NaN; if (value === null) return 0; if (typeof value === 'boolean') return value ? 1 : 0; if (typeof value === 'string') return parseInt(value, 10); if (typeof value === 'symbol' || typeof value === 'object') throw new Error('TYPE ERROR: Unexpected operand type.'); return value; }; /** Returns the timestamp in milliseconds */ EtDatetime.prototype.valueOf = function () { return this.moment; }; /** Alias of `toIso8601String()` */ EtDatetime.prototype.toJSON = function () { return this.toIso8601String(); }; /** Alias of `toIso8601String()` */ EtDatetime.prototype.toISOString = function () { return this.toIso8601String(); }; /** Returns Ethiopic year */ EtDatetime.prototype.getFullYear = function () { return this.year; }; /** Returns Ethiopic month (0-indexed) */ EtDatetime.prototype.getMonth = function () { return this.month - 1; }; /** Returns Ethiopic day */ EtDatetime.prototype.getDate = function () { return this.day; }; /** Returns hour */ EtDatetime.prototype.getHours = function () { return this.hour; }; /** Returns minute */ EtDatetime.prototype.getMinutes = function () { return this.minute; }; /** Returns second */ EtDatetime.prototype.getSeconds = function () { return this.second; }; /** Returns millisecond */ EtDatetime.prototype.getMilliseconds = function () { return this.millisecond; }; /** * Static method that returns the current EtDatetime. */ EtDatetime.now = function () { return new EtDatetime(Date.now()); }; Object.defineProperty(EtDatetime.prototype, Symbol.toStringTag, { /** Customizes output of Object.prototype.toString.call() */ get: function () { return 'EtDatetime'; }, enumerable: true, configurable: true }); /** * Enables primitive coercion: * - String context → ISO string * - Number context → timestamp */ EtDatetime.prototype[Symbol.toPrimitive] = function (hint) { if (hint === 'string' || hint === 'default') return this.toISOString(); if (hint === 'number') return this.valueOf(); return this.toISOString(); }; /** * Returns timestamp in ms (same as valueOf). */ EtDatetime.prototype.getTime = function () { return this.valueOf(); }; /** * Converts EtDatetime to native JavaScript Date. */ EtDatetime.prototype.toDate = function () { return new Date(this.moment); }; /** * Returns the day of the week (0–6), where 0 is Sunday and 6 is Saturday. * Equivalent to JavaScript Date.prototype.getDay(). */ EtDatetime.prototype.getDay = function () { return this.weekday; }; /** * Returns the day of the month (1–31) in UTC. * Equivalent to Date.prototype.getUTCDate(). */ EtDatetime.prototype.getUTCDate = function () { return new Date(this.moment).getUTCDate(); }; /** * Returns the day of the week in UTC (0–6), where 0 is Sunday. * Equivalent to Date.prototype.getUTCDay(). */ EtDatetime.prototype.getUTCDay = function () { return new Date(this.moment).getUTCDay(); }; /** * Returns the full year (e.g. 2024) in UTC. * Equivalent to Date.prototype.getUTCFullYear(). */ EtDatetime.prototype.getUTCFullYear = function () { return new Date(this.moment).getUTCFullYear(); }; /** * Returns the month (0–11) in UTC. * Equivalent to Date.prototype.getUTCMonth(). */ EtDatetime.prototype.getUTCMonth = function () { return new Date(this.moment).getUTCMonth(); }; /** * Returns the hour (0–23) in UTC. * Equivalent to Date.prototype.getUTCHours(). */ EtDatetime.prototype.getUTCHours = function () { return new Date(this.moment).getUTCHours(); }; /** * Returns the minute (0–59) in UTC. * Equivalent to Date.prototype.getUTCMinutes(). */ EtDatetime.prototype.getUTCMinutes = function () { return new Date(this.moment).getUTCMinutes(); }; /** * Returns the second (0–59) in UTC. * Equivalent to Date.prototype.getUTCSeconds(). */ EtDatetime.prototype.getUTCSeconds = function () { return new Date(this.moment).getUTCSeconds(); }; /** * Returns the milliseconds (0–999) in UTC. * Equivalent to Date.prototype.getUTCMilliseconds(). */ EtDatetime.prototype.getUTCMilliseconds = function () { return new Date(this.moment).getUTCMilliseconds(); }; /** * Returns the year minus 1900 (e.g., 124 for 2024). * Deprecated in JavaScript, included here for compatibility. */ EtDatetime.prototype.getYear = function () { return this.getFullYear() - 1900; }; /** * Sets the year (offset from 1900), used for legacy JavaScript compatibility. * Equivalent to Date.prototype.setYear(). * @param year A number representing the year minus 1900 */ EtDatetime.prototype.setYear = function (year) { this.setFullYear(year + 1900); }; /** * Sets the day of the month (1–30 for Ethiopian calendar). * @param day The day of the month to set. */ EtDatetime.prototype.setDate = function (day) { var _a = this, year = _a.year, month = _a.month; this._updateFromComponents(year, month, day, this.hour, this.minute, this.second, this.millisecond); }; /** * Sets the full Ethiopian year. * @param year The full year (e.g. 2016). */ EtDatetime.prototype.setFullYear = function (year) { this._updateFromComponents(year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond); }; /** * Sets the Ethiopian month (0-indexed to match JavaScript Date). * @param month Zero-based month index (0 = Meskerem). */ EtDatetime.prototype.setMonth = function (month) { this._updateFromComponents(this.year, month + 1, this.day, this.hour, this.minute, this.second, this.millisecond); }; /** * Sets the hour of the day (0–23). * @param hours The hour to set. */ EtDatetime.prototype.setHours = function (hours) { this._updateFromComponents(this.year, this.month, this.day, hours, this.minute, this.second, this.millisecond); }; /** * Sets the minute (0–59). * @param minutes The minute to set. */ EtDatetime.prototype.setMinutes = function (minutes) { this._updateFromComponents(this.year, this.month, this.day, this.hour, minutes, this.second, this.millisecond); }; /** * Sets the second (0–59). * @param seconds The second to set. */ EtDatetime.prototype.setSeconds = function (seconds) { this._updateFromComponents(this.year, this.month, this.day, this.hour, this.minute, seconds, this.millisecond); }; /** * Sets the milliseconds (0–999). * @param ms The milliseconds to set. */ EtDatetime.prototype.setMilliseconds = function (ms) { this._updateFromComponents(this.year, this.month, this.day, this.hour, this.minute, this.second, ms); }; /** * Sets the timestamp (in milliseconds since the Unix epoch). * @param timestamp Milliseconds since epoch. */ EtDatetime.prototype.setTime = function (timestamp) { this.fromMillisecondsSinceEpoch(timestamp); }; /** * Sets the UTC day of the month. * @param day The UTC day to set. */ EtDatetime.prototype.setUTCDate = function (day) { var d = new Date(this.moment); d.setUTCDate(day); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC full year. * @param year The UTC year to set. */ EtDatetime.prototype.setUTCFullYear = function (year) { var d = new Date(this.moment); d.setUTCFullYear(year); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC hour. * @param hours The UTC hour to set. */ EtDatetime.prototype.setUTCHours = function (hours) { var d = new Date(this.moment); d.setUTCHours(hours); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC minute. * @param minutes The UTC minutes to set. */ EtDatetime.prototype.setUTCMinutes = function (minutes) { var d = new Date(this.moment); d.setUTCMinutes(minutes); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC second. * @param seconds The UTC seconds to set. */ EtDatetime.prototype.setUTCSeconds = function (seconds) { var d = new Date(this.moment); d.setUTCSeconds(seconds); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC milliseconds. * @param ms The UTC milliseconds to set. */ EtDatetime.prototype.setUTCMilliseconds = function (ms) { var d = new Date(this.moment); d.setUTCMilliseconds(ms); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Sets the UTC month (0–11). * @param month The UTC month to set. */ EtDatetime.prototype.setUTCMonth = function (month) { var d = new Date(this.moment); d.setUTCMonth(month); this.fromMillisecondsSinceEpoch(d.getTime()); }; /** * Updates internal `fixed` and `moment` values from full date-time components. * * @param year Ethiopian year * @param month Ethiopian month (1–13) * @param day Ethiopian day of month (1–30) * @param hour Hour (0–23) * @param minute Minute (0–59) * @param second Second (0–59) * @param millisecond Millisecond (0–999) */ EtDatetime.prototype._updateFromComponents = function (year, month, day, hour, minute, second, millisecond) { this.fixed = this.fixedFromEthiopic(year, month, day); this.moment = this.dateToEpoch(year, month, day, hour, minute, second, millisecond); }; /** * Returns a human-readable date string using system locale. * Equivalent to Date.prototype.toDateString(). */ EtDatetime.prototype.toDateString = function () { return this.toDate().toDateString(); }; /** * Returns a human-readable time string using system locale. * Equivalent to Date.prototype.toTimeString(). */ EtDatetime.prototype.toTimeString = function () { return this.toDate().toTimeString(); }; /** * Returns a UTC date-time string. * Equivalent to Date.prototype.toUTCString(). */ EtDatetime.prototype.toUTCString = function () { return this.toDate().toUTCString(); }; /** * Returns a locale-sensitive string representation of the date and time. * Equivalent to Date.prototype.toLocaleString(). */ EtDatetime.prototype.toLocaleString = function () { return this.toDate().toLocaleString(); }; /** * Returns a locale-sensitive string of just the date portion. * Equivalent to Date.prototype.toLocaleDateString(). */ EtDatetime.prototype.toLocaleDateString = function () { return this.toDate().toLocaleDateString(); }; /** * Returns a locale-sensitive string of just the time portion. * Equivalent to Date.prototype.toLocaleTimeString(). */ EtDatetime.prototype.toLocaleTimeString = function () { return this.toDate().toLocaleTimeString(); }; /** * Returns a Temporal.Instant object representing this date-time. * Requires Temporal API (ES2024) or @js-temporal/polyfill. */ EtDatetime.prototype.toTemporalInstant = function () { return polyfill_1.Temporal.Instant.fromEpochMilliseconds(this.moment); }; return EtDatetime; }()); exports.default = EtDatetime;