{"version":3,"sources":["../src/Zone.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAW,MAAM,iBAAiB,CAAC;AAIjE,8BAAsB,IAAK,YAAW,SAAS,EAAE,UAAU;oBAC5C,GAAG;oBACH,MAAM;sBAEJ,QAAQ,EAAI,MAAM;sBAClB,QAAQ,EAAI,MAAM;IAE/B,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU;IAEhD,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAI1C,eAAe,CAAC,OAAO,EAAE,OAAO;IAIhC,aAAa,CAAC,OAAO,EAAE,OAAO;IAI9B,WAAW,CAAC,OAAO,EAAE,OAAO;IAI5B,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO;IAErC,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM;IAK9B,QAAQ;IAIR,MAAM;IAIN,MAAM,CAAC,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU;IAIpD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAYrC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO;IAKjC,CAAC,SAAS,CAAC,IAAI,CAAC;IAOhB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,OAAO;CAIxC;AAQD,qBAAa,UAAW,SAAQ,IAAK,YAAW,SAAS,EAAE,UAAU;IACjE,MAAM,CAAC,QAAQ,CAAC,GAAG,aAA0B;IAC7C,MAAM,CAAC,QAAQ,CAAC,GAAG,aAAyB;IAE5C,OAAO,CAAC,cAAc,CAAS;gBAEnB,aAAa,EAAE,MAAM;aAK7B,QAAQ;aACR,QAAQ;aACR,aAAa;aACb,YAAY;IAehB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU;IAKvC,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAK1C,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM;IAKzC,MAAM,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO;IAK5B,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAW3C,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAK3C,CAAC,SAAS,CAAC,IAAI,CAAC;IAMhB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;CAIjD","file":"Zone.d.ts","sourcesContent":["/*!\r\n   Copyright 2019 Ron Buckton\r\n\r\n   Licensed under the Apache License, Version 2.0 (the \"License\");\r\n   you may not use this file except in compliance with the License.\r\n   You may obtain a copy of the License at\r\n\r\n       http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n   Unless required by applicable law or agreed to in writing, software\r\n   distributed under the License is distributed on an \"AS IS\" BASIS,\r\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n   See the License for the specific language governing permissions and\r\n   limitations under the License.\r\n*/\r\nimport { compareNumbers, compareStrings, normalizeString, ZONEOFFSET_HASH_SEED, ZONE_HASH_SEED } from './internal/core';\r\nimport { D2 } from \"./internal/formats\";\r\nimport { ZonedDateTime } from './ZonedDateTime';\r\nimport { Instant } from './Instant';\r\nimport { Equatable, Comparable, Equaler } from '@esfx/equatable';\r\n\r\nconst offsetStringRegExp = /^(?<sign>[+-])(?<hours>\\d{2})(?:(?<colon>:)?(?<minutes>\\d{2})(?:\\k<colon>(?<seconds>\\d{2}))?)?$/;\r\n\r\nexport abstract class Zone implements Equatable, Comparable {\r\n    static get UTC() { return UTC; }\r\n    static get SYSTEM() { return SYSTEM; }\r\n\r\n    abstract get ianaZone(): string;\r\n    abstract get timeZone(): string;\r\n\r\n    abstract getOffset(instant: Instant): ZoneOffset;\r\n\r\n    getOffsetSeconds(instant: Instant): number {\r\n        return this.getOffset(instant).offsetSeconds;\r\n    }\r\n\r\n    getOffsetString(instant: Instant) {\r\n        return this.getOffset(instant).offsetString;\r\n    }\r\n\r\n    getZoneString(instant: Instant) {\r\n        return `${this.getOffsetString(instant)}${this.ianaZone ? `[${this.ianaZone}]` : \"\"}`;\r\n    }\r\n\r\n    withInstant(instant: Instant) {\r\n        return new ZonedDateTime(instant, this);\r\n    }\r\n\r\n    abstract equals(other: Zone): boolean;\r\n\r\n    compareTo(other: Zone): number {\r\n        return compareNumbers(this.getOffsetSeconds(Instant.EPOCH), other.getOffsetSeconds(Instant.EPOCH))\r\n            || compareStrings(this.timeZone, other.timeZone);\r\n    }\r\n\r\n    toString() {\r\n        return this.timeZone;\r\n    }\r\n\r\n    toJSON() {\r\n        return this.timeZone;\r\n    }\r\n\r\n    static fromOffset(offsetSeconds: number): ZoneOffset {\r\n        return new ZoneOffset(offsetSeconds);\r\n    }\r\n\r\n    static fromString(zone: string): Zone {\r\n        if (zone === \"Z\" || zone === \"UTC\") return ZoneOffset.UTC;\r\n        if (zone === \"SYSTEM\") return Zone.SYSTEM;\r\n        const match = offsetStringRegExp.exec(normalizeString(zone));\r\n        if (match) {\r\n            const { sign, hours, minutes = \"\", seconds = \"\" } = match.groups!;\r\n            const offsetSeconds = +hours * 3600 + +minutes * 60 + +seconds;\r\n            return new ZoneOffset(sign === \"-\" ? -offsetSeconds : offsetSeconds);\r\n        }\r\n        return new IanaZone(zone);\r\n    }\r\n\r\n    [Equatable.equals](other: unknown) {\r\n        return other instanceof Zone\r\n            && this.equals(other);\r\n    }\r\n\r\n    [Equatable.hash]() {\r\n        let hc = ZONE_HASH_SEED;\r\n        hc = ((hc << 7) | (hc >>> 25)) ^ Equaler.defaultEqualer.hash(this.ianaZone);\r\n        hc = ((hc << 7) | (hc >>> 25)) ^ Equaler.defaultEqualer.hash(this.timeZone);\r\n        return hc;\r\n    }\r\n\r\n    [Comparable.compareTo](other: unknown) {\r\n        if (!(other instanceof Zone)) throw new TypeError();\r\n        return this.compareTo(other);\r\n    }\r\n}\r\n\r\nObject.defineProperty(Zone.prototype, Symbol.toStringTag, {\r\n    writable: true,\r\n    configurable: true,\r\n    value: \"Zone\"\r\n});\r\n\r\nexport class ZoneOffset extends Zone implements Equatable, Comparable {\r\n    static readonly MIN = new ZoneOffset(-64800);\r\n    static readonly MAX = new ZoneOffset(64800);\r\n\r\n    private _offsetSeconds: number;\r\n\r\n    constructor(offsetSeconds: number) {\r\n        super();\r\n        this._offsetSeconds = offsetSeconds;\r\n    }\r\n\r\n    get ianaZone() { return \"\"; }\r\n    get timeZone() { return this.offsetString; }\r\n    get offsetSeconds() { return this._offsetSeconds; }\r\n    get offsetString() {\r\n        let offsetSeconds = this._offsetSeconds;\r\n        if (offsetSeconds === 0) return \"Z\";\r\n        let sign = \"+\";\r\n        if (offsetSeconds < 0) {\r\n            sign = \"-\";\r\n            offsetSeconds = -offsetSeconds;\r\n        }\r\n\r\n        const h = Math.floor(offsetSeconds / 3600);\r\n        const m = Math.floor(offsetSeconds / 60) % 60;\r\n        const s = offsetSeconds % 60;\r\n        return `${sign}${D2(h)}:${D2(m)}${s ? `:${D2(s)}` : \"\"}`;\r\n    }\r\n\r\n    getOffset(instant: Instant): ZoneOffset;\r\n    getOffset(_instant: Instant) {\r\n        return this;\r\n    }\r\n\r\n    getOffsetSeconds(instant: Instant): number;\r\n    getOffsetSeconds(_instant: Instant) {\r\n        return this.offsetSeconds;\r\n    }\r\n\r\n    getOffsetString(instant: Instant): string;\r\n    getOffsetString(_instant: Instant) {\r\n        return this.offsetString;\r\n    }\r\n\r\n    equals(other: Zone): boolean {\r\n        return other instanceof ZoneOffset\r\n            && this._offsetSeconds === other._offsetSeconds;\r\n    }\r\n\r\n    static fromString(text: string): ZoneOffset {\r\n        if (text === \"Z\" || text === \"UTC\") return ZoneOffset.UTC;\r\n        const match = offsetStringRegExp.exec(normalizeString(text));\r\n        if (match) {\r\n            const { sign, hours, minutes = \"\", seconds = \"\" } = match.groups!;\r\n            const offsetSeconds = +hours * 3600 + +minutes * 60 + +seconds;\r\n            return new ZoneOffset(sign === \"-\" ? -offsetSeconds : offsetSeconds);\r\n        }\r\n        throw new SyntaxError(`Invalid offset string '${text}'.`);\r\n    }\r\n\r\n    [Equatable.equals](other: unknown): boolean {\r\n        return other instanceof ZoneOffset\r\n            && this.equals(other);\r\n    }\r\n\r\n    [Equatable.hash]() {\r\n        let hc = ZONEOFFSET_HASH_SEED;\r\n        hc = ((hc << 7) | (hc >>> 25)) ^ Equaler.defaultEqualer.hash(this._offsetSeconds);\r\n        return hc;\r\n    }\r\n\r\n    [Comparable.compareTo](other: unknown): number {\r\n        if (!(other instanceof ZoneOffset)) throw new TypeError();\r\n        return this.compareTo(other);\r\n    }\r\n}\r\n\r\nObject.defineProperty(ZoneOffset.prototype, Symbol.toStringTag, {\r\n    writable: true,\r\n    configurable: true,\r\n    value: \"ZoneOffset\"\r\n});\r\n\r\nconst UTC = new ZoneOffset(0);\r\nconst SYSTEM: Zone = new class extends Zone {\r\n    get ianaZone() { return \"\"; }\r\n    get timeZone() { return \"SYSTEM\"; }\r\n    equals(other: Zone): boolean { return other === SYSTEM; }\r\n    getOffset(instant: Instant) { return new ZoneOffset(new Date(instant.milliseconds).getTimezoneOffset() * -60); }\r\n};\r\n\r\nclass IanaZone extends Zone {\r\n    private _ianaZone: string;\r\n\r\n    constructor(ianaZone: string) {\r\n        super();\r\n        this._ianaZone = ianaZone;\r\n    }\r\n\r\n    get ianaZone() { return this._ianaZone; }\r\n    get timeZone() { return this._ianaZone; }\r\n\r\n    equals(other: Zone): boolean {\r\n        return other instanceof IanaZone\r\n            && this._ianaZone === other._ianaZone;\r\n    }\r\n\r\n    getOffset(instant: Instant) {\r\n        const format = new Intl.DateTimeFormat(\"en-iso\", {\r\n            year: \"numeric\",\r\n            month: \"numeric\",\r\n            day: \"numeric\",\r\n            hour: \"numeric\",\r\n            minute: \"numeric\",\r\n            second: \"numeric\",\r\n            hour12: false,\r\n            timeZone: this._ianaZone\r\n        });\r\n\r\n        let year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;\r\n        for (const part of format.formatToParts(new Date(instant.milliseconds))) {\r\n            switch (part.type) {\r\n                case \"year\": year = +part.value; break;\r\n                case \"month\": month = +part.value; break;\r\n                case \"day\": day = +part.value; break;\r\n                case \"hour\": hour = +part.value; break;\r\n                case \"minute\": minute = +part.value; break;\r\n                case \"second\": second = +part.value; break;\r\n            }\r\n        }\r\n\r\n        const utcTime = Date.UTC(year, month - 1, day, hour, minute, second, instant.milliseconds % 1e3);\r\n        const offsetSeconds = Math.floor((utcTime - instant.milliseconds) / 1e3);\r\n        return new ZoneOffset(offsetSeconds);\r\n    }\r\n}"],"sourceRoot":""}