@digitalwalletcorp/utils 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"date-util-BNe2E-tA.js","sources":["../src/date-util.ts"],"sourcesContent":["import { ZonedDateTime } from './zoned-date-time';\n\n/**\n * 日時として解釈する値。string はISO形式または inputFormat の書式、number は epoch ミリ秒\n * ZonedDateTime は inputTimezone を省略した場合、その ZonedDateTime のタイムゾーンで扱う\n */\nexport type DateInput = string | Date | number | ZonedDateTime | null | undefined;\n\n/** 日時の切り捨て(startOf / endOf)に使う単位 */\nexport type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';\n\n/** 期間の単位 */\nexport type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';\n\n/** 日時の加算・減算に使う期間。負の値で減算になる */\nexport interface Duration {\n years?: number;\n quarters?: number;\n months?: number;\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n}\n\n/**\n * 日時を解釈するときのオプション\n */\nexport interface ParseDateOptions {\n /** 入力の書式。配列の場合は先頭から順に試す。いずれにも一致しない場合はISO形式として解釈する */\n inputFormat?: string | string[];\n /** ゾーン情報を含まない入力をどのタイムゾーンの日時とみなすか(IANA名)。既定は 'UTC' */\n inputTimezone?: string;\n /** 解釈した日時に加算する期間。startOf / endOf より先に適用する */\n duration?: Duration;\n /** 指定した単位の最初の時点に切り捨てる(month なら月初の00:00:00.000) */\n startOf?: DateUnit;\n /** 指定した単位の最後の時点に切り上げる(month なら月末の23:59:59.999) */\n endOf?: DateUnit;\n /** 書式の月名・曜日名を解釈・出力するときのロケール。既定は 'en-US' */\n locale?: string;\n}\n\n/**\n * 日時を文字列にするときのオプション\n */\nexport interface FormatDateOptions extends ParseDateOptions {\n /** 出力の書式。省略時はISO形式 */\n outputFormat?: string;\n /** 出力に使うタイムゾーン(IANA名)。既定は 'UTC' */\n outputTimezone?: string;\n /** 日時として解釈できない値に対する出力。既定は 'Invalid Date' */\n invalidText?: string;\n}\n\n/** タイムゾーンの略称。夏時間のないタイムゾーンでは daylight を持たない */\nexport interface TimezoneAbbreviation {\n standard: string;\n daylight?: string;\n}\n\n/** IANA名をキーにしたタイムゾーンの略称の表 */\nexport type TimezoneAbbreviations = Record<string, TimezoneAbbreviation>;\n\n/**\n * タイムゾーンの略称を解決するときのオプション\n */\nexport interface TimezoneAbbrOptions {\n /** 夏時間かどうかを判定する時点。既定は現在時刻 */\n at?: Date;\n /** 既定の表に追加・上書きする略称 */\n abbreviations?: TimezoneAbbreviations;\n}\n\nconst DEFAULT_TIMEZONE = 'UTC';\n\nconst TIMESTAMP_FORMAT = `yyyy-MM-dd'T'HH:mm:ss.SSSZZ`;\n\n/** 1970-01-01 を表すExcelの日付シリアル値 */\nconst EXCEL_EPOCH_SERIAL = 25569;\n\nconst MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;\n\nconst MILLISECONDS_PER_HOUR = 60 * 60 * 1000;\n\nconst GMT_OFFSET = /GMT[+-]\\d{1,2}(:\\d{2})?/g;\n\n/**\n * 略称の既定の表。略称は世界で一意ではないため(CST は米国中部・中国などで使われる)、このライブラリが採用する表記である\n */\nconst DEFAULT_TIMEZONE_ABBREVIATIONS: TimezoneAbbreviations = {\n 'UTC': { standard: 'UTC' },\n 'Asia/Tokyo': { standard: 'JST' },\n 'Asia/Seoul': { standard: 'KST' },\n 'Asia/Shanghai': { standard: 'CST' },\n 'Asia/Hong_Kong': { standard: 'HKT' },\n 'Asia/Taipei': { standard: 'CST' },\n 'Asia/Singapore': { standard: 'SGT' },\n 'Asia/Manila': { standard: 'PHT' },\n 'Asia/Bangkok': { standard: 'ICT' },\n 'Asia/Ho_Chi_Minh': { standard: 'ICT' },\n 'Asia/Jakarta': { standard: 'WIB' },\n 'Asia/Kolkata': { standard: 'IST' },\n 'Asia/Dubai': { standard: 'GST' },\n 'Australia/Sydney': { standard: 'AEST', daylight: 'AEDT' },\n 'Pacific/Auckland': { standard: 'NZST', daylight: 'NZDT' },\n 'Europe/London': { standard: 'GMT', daylight: 'BST' },\n 'Europe/Paris': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Berlin': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Madrid': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Rome': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Amsterdam': { standard: 'CET', daylight: 'CEST' },\n 'America/New_York': { standard: 'EST', daylight: 'EDT' },\n 'America/Toronto': { standard: 'EST', daylight: 'EDT' },\n 'America/Chicago': { standard: 'CST', daylight: 'CDT' },\n 'America/Denver': { standard: 'MST', daylight: 'MDT' },\n 'America/Phoenix': { standard: 'MST' },\n 'America/Los_Angeles': { standard: 'PST', daylight: 'PDT' },\n 'America/Vancouver': { standard: 'PST', daylight: 'PDT' },\n 'America/Mexico_City': { standard: 'CST' },\n 'America/Sao_Paulo': { standard: 'BRT' }\n};\n\nconst compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions | undefined, predicate: (v1: number, v2: number) => boolean): boolean => {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return false;\n }\n return predicate(d1.toMillis(), d2.toMillis());\n};\n\n/**\n * 値を日時として解釈し、Date を返す\n * duration / startOf / endOf は inputTimezone のゾーンで計算する\n * 解釈できない値、null / undefined / 空文字は null を返す。タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {Date | null}\n */\nexport function parseDate(value: DateInput, options?: ParseDateOptions): Date | null {\n return ZonedDateTime.parse(value, options)?.toDate() ?? null;\n}\n\n/**\n * 値を日時として解釈し、outputTimezone での文字列にする\n * value を省略して options だけを渡した場合は現在時刻を整形する\n * null / undefined / 空文字は空文字を返す。解釈できない値は 'Invalid Date' を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {FormatDateOptions} [options]\n * @returns {string}\n */\nexport function formatDate(options: FormatDateOptions): string;\nexport function formatDate(value: DateInput, options?: FormatDateOptions): string;\nexport function formatDate(value: DateInput | FormatDateOptions, options?: FormatDateOptions): string {\n if (typeof value === 'object' && value !== null && !(value instanceof Date) && !(value instanceof ZonedDateTime)) {\n return formatDate(new Date(), value);\n }\n if (value == null || value === '') {\n return '';\n }\n const d = ZonedDateTime.parse(value, options);\n if (!d) {\n return options?.invalidText ?? 'Invalid Date';\n }\n const output = d.setZone(options?.outputTimezone ?? DEFAULT_TIMEZONE);\n return options?.outputFormat ? output.format(options.outputFormat, { locale: options.locale }) : output.toISO();\n}\n\n/**\n * 値が日時として解釈できるか判定する\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isValid(value: DateInput, options?: ParseDateOptions): boolean {\n return ZonedDateTime.parse(value, options) != null;\n}\n\n/**\n * date1 と date2 が同じ時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSame(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 === v2);\n}\n\n/**\n * date1 が date2 より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 < v2);\n}\n\n/**\n * date1 が date2 と同じか、より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 <= v2);\n}\n\n/**\n * date1 が date2 より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 < v1);\n}\n\n/**\n * date1 が date2 と同じか、より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 <= v1);\n}\n\n/**\n * 値が inputTimezone での今日より前の日付か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDate(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options)?.startOf('day');\n if (!target) {\n return false;\n }\n const today = ZonedDateTime.now(target.timezone).startOf('day');\n return target.lt(today);\n}\n\n/**\n * 値が現在時刻より前か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDateTime(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options);\n return target != null && target.toMillis() < Date.now();\n}\n\n/**\n * date1 − date2 を unit の単位で返す\n * 両方を inputTimezone で unit の始まりに切り捨ててから差を取るため、暦の上での差になる(23:00 と翌 01:00 の days は 1)\n * どちらかが解釈できない場合は NaN を返す\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {TimeUnit} unit\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {number}\n */\nexport function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options?: ParseDateOptions): number {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return NaN;\n }\n return d1.diff(d2, unit);\n}\n\n/**\n * 現在時刻を timezone での 'yyyy-MM-ddTHH:mm:ss.SSS+HH:mm' 形式の文字列で返す\n *\n * @param {string} [timezone] IANA名。既定は 'UTC'\n * @returns {string}\n */\nexport function currentTimestamp(timezone: string = DEFAULT_TIMEZONE): string {\n return ZonedDateTime.now(timezone).format(TIMESTAMP_FORMAT);\n}\n\n/**\n * Excelの日付シリアル値を epoch ミリ秒に変換する\n * Excelの日付シリアル値はゾーンの概念を持たないため、そのままではUTCの日時として変換される\n * シリアル値がどのゾーンの日時かが分かっている場合は offset に時間差を指定する\n *\n * @example\n * convertExcelDateSerialToUnixTimeSerial(45200); // 1696118400000 (2023-10-01T00:00:00Z)\n * convertExcelDateSerialToUnixTimeSerial(45200, { offset: 9 }); // 1696086000000 (2023-10-01T00:00:00+09:00)\n *\n * @param {number} excelDateSerial\n * @param {*} [options]\n * └ offset シリアル値のゾーンのUTCからの時間差(時)\n * @returns {number}\n */\nexport function convertExcelDateSerialToUnixTimeSerial(excelDateSerial: number, options?: {\n offset: number;\n}): number {\n let timeserial = (excelDateSerial - EXCEL_EPOCH_SERIAL) * MILLISECONDS_PER_DAY;\n if (options?.offset) {\n timeserial -= options.offset * MILLISECONDS_PER_HOUR;\n }\n return timeserial;\n}\n\n/**\n * timezone が at の時点で夏時間かどうかを返す\n * at を省略した場合は現在時刻で判定する。at が解釈できない場合は false を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {string} timezone IANA名\n * @param {DateInput} [at] 判定する時点\n * @returns {boolean}\n */\nexport function isInDST(timezone: string, at?: DateInput): boolean {\n const d = at === undefined ? ZonedDateTime.now(timezone) : ZonedDateTime.parse(at)?.setZone(timezone);\n return d?.isInDST ?? false;\n}\n\n/**\n * タイムゾーンの略称を返す。夏時間の期間中は夏時間の略称を返す\n * 既定の表にない場合は null を返す。表は options.abbreviations で追加・上書きできる\n *\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string | null}\n */\nexport function getTimezoneAbbr(timezone: string, options?: TimezoneAbbrOptions): string | null {\n const definition = { ...DEFAULT_TIMEZONE_ABBREVIATIONS, ...options?.abbreviations }[timezone];\n if (!definition) {\n return null;\n }\n if (definition.daylight) {\n const d = ZonedDateTime.parse(options?.at ?? new Date())?.setZone(timezone);\n if (d?.isInDST) {\n return definition.daylight;\n }\n }\n return definition.standard;\n}\n\n/**\n * 文字列中の 'GMT+9' のようなオフセット表記を、timezone の略称に置き換える\n * 略称が解決できない場合は文字列をそのまま返す\n *\n * @param {string} text\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string}\n */\nexport function applyTimezoneAbbr(text: string, timezone: string, options?: TimezoneAbbrOptions): string {\n const abbr = getTimezoneAbbr(timezone, options);\n return abbr == null ? text : text.replace(GMT_OFFSET, abbr);\n}\n"],"names":["DEFAULT_TIMEZONE","TIMESTAMP_FORMAT","EXCEL_EPOCH_SERIAL","MILLISECONDS_PER_DAY","MILLISECONDS_PER_HOUR","GMT_OFFSET","DEFAULT_TIMEZONE_ABBREVIATIONS","compare","date1","date2","options","predicate","d1","ZonedDateTime","d2","parseDate","value","formatDate","d","output","isValid","isSame","v1","v2","isBefore","isSameOrBefore","isAfter","isSameOrAfter","isPastDate","target","today","isPastDateTime","diff","unit","currentTimestamp","timezone","convertExcelDateSerialToUnixTimeSerial","excelDateSerial","timeserial","isInDST","at","getTimezoneAbbr","definition","applyTimezoneAbbr","text","abbr"],"mappings":"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"}
1
+ {"version":3,"file":"date-util-BNe2E-tA.js","sources":["../src/date-util.ts"],"sourcesContent":["import { ZonedDateTime } from './zoned-date-time';\n\n/**\n * 日時として解釈する値。string はISO形式または inputFormat の書式、number は epoch ミリ秒\n * ZonedDateTime は inputTimezone を省略した場合、その ZonedDateTime のタイムゾーンで扱う\n */\nexport type DateInput = string | Date | number | ZonedDateTime | null | undefined;\n\n/** 日時の切り捨て(startOf / endOf)に使う単位 */\nexport type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';\n\n/** 期間の単位 */\nexport type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'quarters' | 'years';\n\n/** 日時の加算・減算に使う期間。負の値で減算になる */\nexport interface Duration {\n years?: number;\n quarters?: number;\n months?: number;\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n}\n\n/**\n * 日時を解釈するときのオプション\n */\nexport interface ParseDateOptions {\n /** 入力の書式。配列の場合は先頭から順に試す。いずれにも一致しない場合はISO形式として解釈する */\n inputFormat?: string | string[];\n /** ゾーン情報を含まない入力をどのタイムゾーンの日時とみなすか(IANA名)。既定は 'UTC' */\n inputTimezone?: string;\n /** 解釈した日時に加算する期間。startOf / endOf より先に適用する */\n duration?: Duration;\n /** 指定した単位の最初の時点に切り捨てる(month なら月初の00:00:00.000) */\n startOf?: DateUnit;\n /** 指定した単位の最後の時点に切り上げる(month なら月末の23:59:59.999) */\n endOf?: DateUnit;\n /** 書式の月名・曜日名を解釈・出力するときのロケール。既定は 'en-US' */\n locale?: string;\n}\n\n/**\n * 日時を文字列にするときのオプション\n */\nexport interface FormatDateOptions extends ParseDateOptions {\n /** 出力の書式。省略時はISO形式 */\n outputFormat?: string;\n /** 出力に使うタイムゾーン(IANA名)。既定は 'UTC' */\n outputTimezone?: string;\n /** 日時として解釈できない値に対する出力。既定は 'Invalid Date' */\n invalidText?: string;\n}\n\n/** タイムゾーンの略称。夏時間のないタイムゾーンでは daylight を持たない */\nexport interface TimezoneAbbreviation {\n standard: string;\n daylight?: string;\n}\n\n/** IANA名をキーにしたタイムゾーンの略称の表 */\nexport type TimezoneAbbreviations = Record<string, TimezoneAbbreviation>;\n\n/**\n * タイムゾーンの略称を解決するときのオプション\n */\nexport interface TimezoneAbbrOptions {\n /** 夏時間かどうかを判定する時点。既定は現在時刻 */\n at?: Date;\n /** 既定の表に追加・上書きする略称 */\n abbreviations?: TimezoneAbbreviations;\n}\n\nconst DEFAULT_TIMEZONE = 'UTC';\n\nconst TIMESTAMP_FORMAT = `yyyy-MM-dd'T'HH:mm:ss.SSSZZ`;\n\n/** 1970-01-01 を表すExcelの日付シリアル値 */\nconst EXCEL_EPOCH_SERIAL = 25569;\n\nconst MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;\n\nconst MILLISECONDS_PER_HOUR = 60 * 60 * 1000;\n\nconst GMT_OFFSET = /GMT[+-]\\d{1,2}(:\\d{2})?/g;\n\n/**\n * 略称の既定の表。略称は世界で一意ではないため(CST は米国中部・中国などで使われる)、このライブラリが採用する表記である\n */\nconst DEFAULT_TIMEZONE_ABBREVIATIONS: TimezoneAbbreviations = {\n 'UTC': { standard: 'UTC' },\n 'Asia/Tokyo': { standard: 'JST' },\n 'Asia/Seoul': { standard: 'KST' },\n 'Asia/Shanghai': { standard: 'CST' },\n 'Asia/Hong_Kong': { standard: 'HKT' },\n 'Asia/Taipei': { standard: 'CST' },\n 'Asia/Singapore': { standard: 'SGT' },\n 'Asia/Manila': { standard: 'PHT' },\n 'Asia/Bangkok': { standard: 'ICT' },\n 'Asia/Ho_Chi_Minh': { standard: 'ICT' },\n 'Asia/Jakarta': { standard: 'WIB' },\n 'Asia/Kolkata': { standard: 'IST' },\n 'Asia/Dubai': { standard: 'GST' },\n 'Australia/Sydney': { standard: 'AEST', daylight: 'AEDT' },\n 'Pacific/Auckland': { standard: 'NZST', daylight: 'NZDT' },\n 'Europe/London': { standard: 'GMT', daylight: 'BST' },\n 'Europe/Paris': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Berlin': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Madrid': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Rome': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Amsterdam': { standard: 'CET', daylight: 'CEST' },\n 'America/New_York': { standard: 'EST', daylight: 'EDT' },\n 'America/Toronto': { standard: 'EST', daylight: 'EDT' },\n 'America/Chicago': { standard: 'CST', daylight: 'CDT' },\n 'America/Denver': { standard: 'MST', daylight: 'MDT' },\n 'America/Phoenix': { standard: 'MST' },\n 'America/Los_Angeles': { standard: 'PST', daylight: 'PDT' },\n 'America/Vancouver': { standard: 'PST', daylight: 'PDT' },\n 'America/Mexico_City': { standard: 'CST' },\n 'America/Sao_Paulo': { standard: 'BRT' }\n};\n\nconst compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions | undefined, predicate: (v1: number, v2: number) => boolean): boolean => {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return false;\n }\n return predicate(d1.toMillis(), d2.toMillis());\n};\n\n/**\n * 値を日時として解釈し、Date を返す\n * duration / startOf / endOf は inputTimezone のゾーンで計算する\n * 解釈できない値、null / undefined / 空文字は null を返す。タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {Date | null}\n */\nexport function parseDate(value: DateInput, options?: ParseDateOptions): Date | null {\n return ZonedDateTime.parse(value, options)?.toDate() ?? null;\n}\n\n/**\n * 値を日時として解釈し、outputTimezone での文字列にする\n * value を省略して options だけを渡した場合は現在時刻を整形する\n * null / undefined / 空文字は空文字を返す。解釈できない値は 'Invalid Date' を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {FormatDateOptions} [options]\n * @returns {string}\n */\nexport function formatDate(options: FormatDateOptions): string;\nexport function formatDate(value: DateInput, options?: FormatDateOptions): string;\nexport function formatDate(value: DateInput | FormatDateOptions, options?: FormatDateOptions): string {\n if (typeof value === 'object' && value !== null && !(value instanceof Date) && !(value instanceof ZonedDateTime)) {\n return formatDate(new Date(), value);\n }\n if (value == null || value === '') {\n return '';\n }\n const d = ZonedDateTime.parse(value, options);\n if (!d) {\n return options?.invalidText ?? 'Invalid Date';\n }\n const output = d.setZone(options?.outputTimezone ?? DEFAULT_TIMEZONE);\n return options?.outputFormat ? output.format(options.outputFormat, { locale: options.locale }) : output.toISO();\n}\n\n/**\n * 値が日時として解釈できるか判定する\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isValid(value: DateInput, options?: ParseDateOptions): boolean {\n return ZonedDateTime.parse(value, options) != null;\n}\n\n/**\n * date1 と date2 が同じ時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSame(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 === v2);\n}\n\n/**\n * date1 が date2 より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 < v2);\n}\n\n/**\n * date1 が date2 と同じか、より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 <= v2);\n}\n\n/**\n * date1 が date2 より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 < v1);\n}\n\n/**\n * date1 が date2 と同じか、より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 <= v1);\n}\n\n/**\n * 値が inputTimezone での今日より前の日付か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDate(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options)?.startOf('day');\n if (!target) {\n return false;\n }\n const today = ZonedDateTime.now(target.timezone).startOf('day');\n return target.lt(today);\n}\n\n/**\n * 値が現在時刻より前か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDateTime(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options);\n return target != null && target.toMillis() < Date.now();\n}\n\n/**\n * date1 − date2 を unit の単位で返す\n * 両方を inputTimezone で unit の始まりに切り捨ててから差を取るため、暦の上での差になる(23:00 と翌 01:00 の days は 1)\n * どちらかが解釈できない場合は NaN を返す\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {TimeUnit} unit\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {number}\n */\nexport function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options?: ParseDateOptions): number {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return NaN;\n }\n return d1.diff(d2, unit);\n}\n\n/**\n * 現在時刻を timezone での 'yyyy-MM-ddTHH:mm:ss.SSS+HH:mm' 形式の文字列で返す\n *\n * @param {string} [timezone] IANA名。既定は 'UTC'\n * @returns {string}\n */\nexport function currentTimestamp(timezone: string = DEFAULT_TIMEZONE): string {\n return ZonedDateTime.now(timezone).format(TIMESTAMP_FORMAT);\n}\n\n/**\n * Excelの日付シリアル値を epoch ミリ秒に変換する\n * Excelの日付シリアル値はゾーンの概念を持たないため、そのままではUTCの日時として変換される\n * シリアル値がどのゾーンの日時かが分かっている場合は offset に時間差を指定する\n *\n * @example\n * convertExcelDateSerialToUnixTimeSerial(45200); // 1696118400000 (2023-10-01T00:00:00Z)\n * convertExcelDateSerialToUnixTimeSerial(45200, { offset: 9 }); // 1696086000000 (2023-10-01T00:00:00+09:00)\n *\n * @param {number} excelDateSerial\n * @param {*} [options]\n * └ offset シリアル値のゾーンのUTCからの時間差(時)\n * @returns {number}\n */\nexport function convertExcelDateSerialToUnixTimeSerial(excelDateSerial: number, options?: {\n offset: number;\n}): number {\n let timeserial = (excelDateSerial - EXCEL_EPOCH_SERIAL) * MILLISECONDS_PER_DAY;\n if (options?.offset) {\n timeserial -= options.offset * MILLISECONDS_PER_HOUR;\n }\n return timeserial;\n}\n\n/**\n * timezone が at の時点で夏時間かどうかを返す\n * at を省略した場合は現在時刻で判定する。at が解釈できない場合は false を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {string} timezone IANA名\n * @param {DateInput} [at] 判定する時点\n * @returns {boolean}\n */\nexport function isInDST(timezone: string, at?: DateInput): boolean {\n const d = at === undefined ? ZonedDateTime.now(timezone) : ZonedDateTime.parse(at)?.setZone(timezone);\n return d?.isInDST ?? false;\n}\n\n/**\n * タイムゾーンの略称を返す。夏時間の期間中は夏時間の略称を返す\n * 既定の表にない場合は null を返す。表は options.abbreviations で追加・上書きできる\n *\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string | null}\n */\nexport function getTimezoneAbbr(timezone: string, options?: TimezoneAbbrOptions): string | null {\n const definition = { ...DEFAULT_TIMEZONE_ABBREVIATIONS, ...options?.abbreviations }[timezone];\n if (!definition) {\n return null;\n }\n if (definition.daylight) {\n const d = ZonedDateTime.parse(options?.at ?? new Date())?.setZone(timezone);\n if (d?.isInDST) {\n return definition.daylight;\n }\n }\n return definition.standard;\n}\n\n/**\n * 文字列中の 'GMT+9' のようなオフセット表記を、timezone の略称に置き換える\n * 略称が解決できない場合は文字列をそのまま返す\n *\n * @param {string} text\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string}\n */\nexport function applyTimezoneAbbr(text: string, timezone: string, options?: TimezoneAbbrOptions): string {\n const abbr = getTimezoneAbbr(timezone, options);\n return abbr == null ? text : text.replace(GMT_OFFSET, abbr);\n}\n"],"names":["DEFAULT_TIMEZONE","TIMESTAMP_FORMAT","EXCEL_EPOCH_SERIAL","MILLISECONDS_PER_DAY","MILLISECONDS_PER_HOUR","GMT_OFFSET","DEFAULT_TIMEZONE_ABBREVIATIONS","compare","date1","date2","options","predicate","d1","ZonedDateTime","d2","parseDate","value","formatDate","d","output","isValid","isSame","v1","v2","isBefore","isSameOrBefore","isAfter","isSameOrAfter","isPastDate","target","today","isPastDateTime","diff","unit","currentTimestamp","timezone","convertExcelDateSerialToUnixTimeSerial","excelDateSerial","timeserial","isInDST","at","getTimezoneAbbr","definition","applyTimezoneAbbr","text","abbr"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"date-util-CZmiQEYH.cjs","sources":["../src/date-util.ts"],"sourcesContent":["import { ZonedDateTime } from './zoned-date-time';\n\n/**\n * 日時として解釈する値。string はISO形式または inputFormat の書式、number は epoch ミリ秒\n * ZonedDateTime は inputTimezone を省略した場合、その ZonedDateTime のタイムゾーンで扱う\n */\nexport type DateInput = string | Date | number | ZonedDateTime | null | undefined;\n\n/** 日時の切り捨て(startOf / endOf)に使う単位 */\nexport type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';\n\n/** 期間の単位 */\nexport type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';\n\n/** 日時の加算・減算に使う期間。負の値で減算になる */\nexport interface Duration {\n years?: number;\n quarters?: number;\n months?: number;\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n}\n\n/**\n * 日時を解釈するときのオプション\n */\nexport interface ParseDateOptions {\n /** 入力の書式。配列の場合は先頭から順に試す。いずれにも一致しない場合はISO形式として解釈する */\n inputFormat?: string | string[];\n /** ゾーン情報を含まない入力をどのタイムゾーンの日時とみなすか(IANA名)。既定は 'UTC' */\n inputTimezone?: string;\n /** 解釈した日時に加算する期間。startOf / endOf より先に適用する */\n duration?: Duration;\n /** 指定した単位の最初の時点に切り捨てる(month なら月初の00:00:00.000) */\n startOf?: DateUnit;\n /** 指定した単位の最後の時点に切り上げる(month なら月末の23:59:59.999) */\n endOf?: DateUnit;\n /** 書式の月名・曜日名を解釈・出力するときのロケール。既定は 'en-US' */\n locale?: string;\n}\n\n/**\n * 日時を文字列にするときのオプション\n */\nexport interface FormatDateOptions extends ParseDateOptions {\n /** 出力の書式。省略時はISO形式 */\n outputFormat?: string;\n /** 出力に使うタイムゾーン(IANA名)。既定は 'UTC' */\n outputTimezone?: string;\n /** 日時として解釈できない値に対する出力。既定は 'Invalid Date' */\n invalidText?: string;\n}\n\n/** タイムゾーンの略称。夏時間のないタイムゾーンでは daylight を持たない */\nexport interface TimezoneAbbreviation {\n standard: string;\n daylight?: string;\n}\n\n/** IANA名をキーにしたタイムゾーンの略称の表 */\nexport type TimezoneAbbreviations = Record<string, TimezoneAbbreviation>;\n\n/**\n * タイムゾーンの略称を解決するときのオプション\n */\nexport interface TimezoneAbbrOptions {\n /** 夏時間かどうかを判定する時点。既定は現在時刻 */\n at?: Date;\n /** 既定の表に追加・上書きする略称 */\n abbreviations?: TimezoneAbbreviations;\n}\n\nconst DEFAULT_TIMEZONE = 'UTC';\n\nconst TIMESTAMP_FORMAT = `yyyy-MM-dd'T'HH:mm:ss.SSSZZ`;\n\n/** 1970-01-01 を表すExcelの日付シリアル値 */\nconst EXCEL_EPOCH_SERIAL = 25569;\n\nconst MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;\n\nconst MILLISECONDS_PER_HOUR = 60 * 60 * 1000;\n\nconst GMT_OFFSET = /GMT[+-]\\d{1,2}(:\\d{2})?/g;\n\n/**\n * 略称の既定の表。略称は世界で一意ではないため(CST は米国中部・中国などで使われる)、このライブラリが採用する表記である\n */\nconst DEFAULT_TIMEZONE_ABBREVIATIONS: TimezoneAbbreviations = {\n 'UTC': { standard: 'UTC' },\n 'Asia/Tokyo': { standard: 'JST' },\n 'Asia/Seoul': { standard: 'KST' },\n 'Asia/Shanghai': { standard: 'CST' },\n 'Asia/Hong_Kong': { standard: 'HKT' },\n 'Asia/Taipei': { standard: 'CST' },\n 'Asia/Singapore': { standard: 'SGT' },\n 'Asia/Manila': { standard: 'PHT' },\n 'Asia/Bangkok': { standard: 'ICT' },\n 'Asia/Ho_Chi_Minh': { standard: 'ICT' },\n 'Asia/Jakarta': { standard: 'WIB' },\n 'Asia/Kolkata': { standard: 'IST' },\n 'Asia/Dubai': { standard: 'GST' },\n 'Australia/Sydney': { standard: 'AEST', daylight: 'AEDT' },\n 'Pacific/Auckland': { standard: 'NZST', daylight: 'NZDT' },\n 'Europe/London': { standard: 'GMT', daylight: 'BST' },\n 'Europe/Paris': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Berlin': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Madrid': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Rome': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Amsterdam': { standard: 'CET', daylight: 'CEST' },\n 'America/New_York': { standard: 'EST', daylight: 'EDT' },\n 'America/Toronto': { standard: 'EST', daylight: 'EDT' },\n 'America/Chicago': { standard: 'CST', daylight: 'CDT' },\n 'America/Denver': { standard: 'MST', daylight: 'MDT' },\n 'America/Phoenix': { standard: 'MST' },\n 'America/Los_Angeles': { standard: 'PST', daylight: 'PDT' },\n 'America/Vancouver': { standard: 'PST', daylight: 'PDT' },\n 'America/Mexico_City': { standard: 'CST' },\n 'America/Sao_Paulo': { standard: 'BRT' }\n};\n\nconst compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions | undefined, predicate: (v1: number, v2: number) => boolean): boolean => {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return false;\n }\n return predicate(d1.toMillis(), d2.toMillis());\n};\n\n/**\n * 値を日時として解釈し、Date を返す\n * duration / startOf / endOf は inputTimezone のゾーンで計算する\n * 解釈できない値、null / undefined / 空文字は null を返す。タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {Date | null}\n */\nexport function parseDate(value: DateInput, options?: ParseDateOptions): Date | null {\n return ZonedDateTime.parse(value, options)?.toDate() ?? null;\n}\n\n/**\n * 値を日時として解釈し、outputTimezone での文字列にする\n * value を省略して options だけを渡した場合は現在時刻を整形する\n * null / undefined / 空文字は空文字を返す。解釈できない値は 'Invalid Date' を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {FormatDateOptions} [options]\n * @returns {string}\n */\nexport function formatDate(options: FormatDateOptions): string;\nexport function formatDate(value: DateInput, options?: FormatDateOptions): string;\nexport function formatDate(value: DateInput | FormatDateOptions, options?: FormatDateOptions): string {\n if (typeof value === 'object' && value !== null && !(value instanceof Date) && !(value instanceof ZonedDateTime)) {\n return formatDate(new Date(), value);\n }\n if (value == null || value === '') {\n return '';\n }\n const d = ZonedDateTime.parse(value, options);\n if (!d) {\n return options?.invalidText ?? 'Invalid Date';\n }\n const output = d.setZone(options?.outputTimezone ?? DEFAULT_TIMEZONE);\n return options?.outputFormat ? output.format(options.outputFormat, { locale: options.locale }) : output.toISO();\n}\n\n/**\n * 値が日時として解釈できるか判定する\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isValid(value: DateInput, options?: ParseDateOptions): boolean {\n return ZonedDateTime.parse(value, options) != null;\n}\n\n/**\n * date1 と date2 が同じ時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSame(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 === v2);\n}\n\n/**\n * date1 が date2 より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 < v2);\n}\n\n/**\n * date1 が date2 と同じか、より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 <= v2);\n}\n\n/**\n * date1 が date2 より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 < v1);\n}\n\n/**\n * date1 が date2 と同じか、より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 <= v1);\n}\n\n/**\n * 値が inputTimezone での今日より前の日付か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDate(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options)?.startOf('day');\n if (!target) {\n return false;\n }\n const today = ZonedDateTime.now(target.timezone).startOf('day');\n return target.lt(today);\n}\n\n/**\n * 値が現在時刻より前か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDateTime(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options);\n return target != null && target.toMillis() < Date.now();\n}\n\n/**\n * date1 − date2 を unit の単位で返す\n * 両方を inputTimezone で unit の始まりに切り捨ててから差を取るため、暦の上での差になる(23:00 と翌 01:00 の days は 1)\n * どちらかが解釈できない場合は NaN を返す\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {TimeUnit} unit\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {number}\n */\nexport function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options?: ParseDateOptions): number {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return NaN;\n }\n return d1.diff(d2, unit);\n}\n\n/**\n * 現在時刻を timezone での 'yyyy-MM-ddTHH:mm:ss.SSS+HH:mm' 形式の文字列で返す\n *\n * @param {string} [timezone] IANA名。既定は 'UTC'\n * @returns {string}\n */\nexport function currentTimestamp(timezone: string = DEFAULT_TIMEZONE): string {\n return ZonedDateTime.now(timezone).format(TIMESTAMP_FORMAT);\n}\n\n/**\n * Excelの日付シリアル値を epoch ミリ秒に変換する\n * Excelの日付シリアル値はゾーンの概念を持たないため、そのままではUTCの日時として変換される\n * シリアル値がどのゾーンの日時かが分かっている場合は offset に時間差を指定する\n *\n * @example\n * convertExcelDateSerialToUnixTimeSerial(45200); // 1696118400000 (2023-10-01T00:00:00Z)\n * convertExcelDateSerialToUnixTimeSerial(45200, { offset: 9 }); // 1696086000000 (2023-10-01T00:00:00+09:00)\n *\n * @param {number} excelDateSerial\n * @param {*} [options]\n * └ offset シリアル値のゾーンのUTCからの時間差(時)\n * @returns {number}\n */\nexport function convertExcelDateSerialToUnixTimeSerial(excelDateSerial: number, options?: {\n offset: number;\n}): number {\n let timeserial = (excelDateSerial - EXCEL_EPOCH_SERIAL) * MILLISECONDS_PER_DAY;\n if (options?.offset) {\n timeserial -= options.offset * MILLISECONDS_PER_HOUR;\n }\n return timeserial;\n}\n\n/**\n * timezone が at の時点で夏時間かどうかを返す\n * at を省略した場合は現在時刻で判定する。at が解釈できない場合は false を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {string} timezone IANA名\n * @param {DateInput} [at] 判定する時点\n * @returns {boolean}\n */\nexport function isInDST(timezone: string, at?: DateInput): boolean {\n const d = at === undefined ? ZonedDateTime.now(timezone) : ZonedDateTime.parse(at)?.setZone(timezone);\n return d?.isInDST ?? false;\n}\n\n/**\n * タイムゾーンの略称を返す。夏時間の期間中は夏時間の略称を返す\n * 既定の表にない場合は null を返す。表は options.abbreviations で追加・上書きできる\n *\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string | null}\n */\nexport function getTimezoneAbbr(timezone: string, options?: TimezoneAbbrOptions): string | null {\n const definition = { ...DEFAULT_TIMEZONE_ABBREVIATIONS, ...options?.abbreviations }[timezone];\n if (!definition) {\n return null;\n }\n if (definition.daylight) {\n const d = ZonedDateTime.parse(options?.at ?? new Date())?.setZone(timezone);\n if (d?.isInDST) {\n return definition.daylight;\n }\n }\n return definition.standard;\n}\n\n/**\n * 文字列中の 'GMT+9' のようなオフセット表記を、timezone の略称に置き換える\n * 略称が解決できない場合は文字列をそのまま返す\n *\n * @param {string} text\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string}\n */\nexport function applyTimezoneAbbr(text: string, timezone: string, options?: TimezoneAbbrOptions): string {\n const abbr = getTimezoneAbbr(timezone, options);\n return abbr == null ? text : text.replace(GMT_OFFSET, abbr);\n}\n"],"names":["DEFAULT_TIMEZONE","TIMESTAMP_FORMAT","EXCEL_EPOCH_SERIAL","MILLISECONDS_PER_DAY","MILLISECONDS_PER_HOUR","GMT_OFFSET","DEFAULT_TIMEZONE_ABBREVIATIONS","compare","date1","date2","options","predicate","d1","ZonedDateTime","d2","parseDate","value","formatDate","d","output","isValid","isSame","v1","v2","isBefore","isSameOrBefore","isAfter","isSameOrAfter","isPastDate","target","today","isPastDateTime","diff","unit","currentTimestamp","timezone","convertExcelDateSerialToUnixTimeSerial","excelDateSerial","timeserial","isInDST","at","getTimezoneAbbr","definition","applyTimezoneAbbr","text","abbr"],"mappings":"sDA4EMA,EAAmB,MAEnBC,EAAmB,8BAGnBC,EAAqB,MAErBC,EAAuB,KAAU,GAAK,IAEtCC,EAAwB,KAAU,IAElCC,EAAa,2BAKbC,EAAwD,CAC5D,IAAO,CAAE,SAAU,KAAA,EACnB,aAAc,CAAE,SAAU,KAAA,EAC1B,aAAc,CAAE,SAAU,KAAA,EAC1B,gBAAiB,CAAE,SAAU,KAAA,EAC7B,iBAAkB,CAAE,SAAU,KAAA,EAC9B,cAAe,CAAE,SAAU,KAAA,EAC3B,iBAAkB,CAAE,SAAU,KAAA,EAC9B,cAAe,CAAE,SAAU,KAAA,EAC3B,eAAgB,CAAE,SAAU,KAAA,EAC5B,mBAAoB,CAAE,SAAU,KAAA,EAChC,eAAgB,CAAE,SAAU,KAAA,EAC5B,eAAgB,CAAE,SAAU,KAAA,EAC5B,aAAc,CAAE,SAAU,KAAA,EAC1B,mBAAoB,CAAE,SAAU,OAAQ,SAAU,MAAA,EAClD,mBAAoB,CAAE,SAAU,OAAQ,SAAU,MAAA,EAClD,gBAAiB,CAAE,SAAU,MAAO,SAAU,KAAA,EAC9C,eAAgB,CAAE,SAAU,MAAO,SAAU,MAAA,EAC7C,gBAAiB,CAAE,SAAU,MAAO,SAAU,MAAA,EAC9C,gBAAiB,CAAE,SAAU,MAAO,SAAU,MAAA,EAC9C,cAAe,CAAE,SAAU,MAAO,SAAU,MAAA,EAC5C,mBAAoB,CAAE,SAAU,MAAO,SAAU,MAAA,EACjD,mBAAoB,CAAE,SAAU,MAAO,SAAU,KAAA,EACjD,kBAAmB,CAAE,SAAU,MAAO,SAAU,KAAA,EAChD,kBAAmB,CAAE,SAAU,MAAO,SAAU,KAAA,EAChD,iBAAkB,CAAE,SAAU,MAAO,SAAU,KAAA,EAC/C,kBAAmB,CAAE,SAAU,KAAA,EAC/B,sBAAuB,CAAE,SAAU,MAAO,SAAU,KAAA,EACpD,oBAAqB,CAAE,SAAU,MAAO,SAAU,KAAA,EAClD,sBAAuB,CAAE,SAAU,KAAA,EACnC,oBAAqB,CAAE,SAAU,KAAA,CACnC,EAEMC,EAAU,CAACC,EAAkBC,EAAkBC,EAAuCC,IAA4D,CACtJ,MAAMC,EAAKC,EAAAA,cAAc,MAAML,EAAOE,CAAO,EACvCI,EAAKD,EAAAA,cAAc,MAAMJ,EAAOC,CAAO,EAC7C,MAAI,CAACE,GAAM,CAACE,EACH,GAEFH,EAAUC,EAAG,SAAA,EAAYE,EAAG,UAAU,CAC/C,EAWO,SAASC,EAAUC,EAAkBN,EAAyC,CACnF,OAAOG,EAAAA,cAAc,MAAMG,EAAON,CAAO,GAAG,UAAY,IAC1D,CAcO,SAASO,EAAWD,EAAsCN,EAAqC,CACpG,GAAI,OAAOM,GAAU,UAAYA,IAAU,MAAQ,EAAEA,aAAiB,OAAS,EAAEA,aAAiBH,EAAAA,eAChG,OAAOI,EAAW,IAAI,KAAQD,CAAK,EAErC,GAAIA,GAAS,MAAQA,IAAU,GAC7B,MAAO,GAET,MAAME,EAAIL,EAAAA,cAAc,MAAMG,EAAON,CAAO,EAC5C,GAAI,CAACQ,EACH,OAAOR,GAAS,aAAe,eAEjC,MAAMS,EAASD,EAAE,QAAQR,GAAS,gBAAkBV,CAAgB,EACpE,OAAOU,GAAS,aAAeS,EAAO,OAAOT,EAAQ,aAAc,CAAE,OAAQA,EAAQ,MAAA,CAAQ,EAAIS,EAAO,MAAA,CAC1G,CASO,SAASC,EAAQJ,EAAkBN,EAAqC,CAC7E,OAAOG,EAAAA,cAAc,MAAMG,EAAON,CAAO,GAAK,IAChD,CAUO,SAASW,EAAOb,EAAkBC,EAAkBC,EAAqC,CAC9F,OAAOH,EAAQC,EAAOC,EAAOC,EAAS,CAACY,EAAIC,IAAOD,IAAOC,CAAE,CAC7D,CAUO,SAASC,EAAShB,EAAkBC,EAAkBC,EAAqC,CAChG,OAAOH,EAAQC,EAAOC,EAAOC,EAAS,CAACY,EAAIC,IAAOD,EAAKC,CAAE,CAC3D,CAUO,SAASE,EAAejB,EAAkBC,EAAkBC,EAAqC,CACtG,OAAOH,EAAQC,EAAOC,EAAOC,EAAS,CAACY,EAAIC,IAAOD,GAAMC,CAAE,CAC5D,CAUO,SAASG,EAAQlB,EAAkBC,EAAkBC,EAAqC,CAC/F,OAAOH,EAAQC,EAAOC,EAAOC,EAAS,CAACY,EAAIC,IAAOA,EAAKD,CAAE,CAC3D,CAUO,SAASK,EAAcnB,EAAkBC,EAAkBC,EAAqC,CACrG,OAAOH,EAAQC,EAAOC,EAAOC,EAAS,CAACY,EAAIC,IAAOA,GAAMD,CAAE,CAC5D,CASO,SAASM,EAAWZ,EAAkBN,EAAqC,CAChF,MAAMmB,EAAShB,EAAAA,cAAc,MAAMG,EAAON,CAAO,GAAG,QAAQ,KAAK,EACjE,GAAI,CAACmB,EACH,MAAO,GAET,MAAMC,EAAQjB,EAAAA,cAAc,IAAIgB,EAAO,QAAQ,EAAE,QAAQ,KAAK,EAC9D,OAAOA,EAAO,GAAGC,CAAK,CACxB,CASO,SAASC,EAAef,EAAkBN,EAAqC,CACpF,MAAMmB,EAAShB,EAAAA,cAAc,MAAMG,EAAON,CAAO,EACjD,OAAOmB,GAAU,MAAQA,EAAO,SAAA,EAAa,KAAK,IAAA,CACpD,CAaO,SAASG,EAAKxB,EAAkBC,EAAkBwB,EAAgBvB,EAAoC,CAC3G,MAAME,EAAKC,EAAAA,cAAc,MAAML,EAAOE,CAAO,EACvCI,EAAKD,EAAAA,cAAc,MAAMJ,EAAOC,CAAO,EAC7C,MAAI,CAACE,GAAM,CAACE,EACH,IAEFF,EAAG,KAAKE,EAAImB,CAAI,CACzB,CAQO,SAASC,EAAiBC,EAAmBnC,EAA0B,CAC5E,OAAOa,EAAAA,cAAc,IAAIsB,CAAQ,EAAE,OAAOlC,CAAgB,CAC5D,CAgBO,SAASmC,EAAuCC,EAAyB3B,EAErE,CACT,IAAI4B,GAAcD,EAAkBnC,GAAsBC,EAC1D,OAAIO,GAAS,SACX4B,GAAc5B,EAAQ,OAASN,GAE1BkC,CACT,CAWO,SAASC,EAAQJ,EAAkBK,EAAyB,CAEjE,OADUA,IAAO,OAAY3B,EAAAA,cAAc,IAAIsB,CAAQ,EAAItB,EAAAA,cAAc,MAAM2B,CAAE,GAAG,QAAQL,CAAQ,IAC1F,SAAW,EACvB,CAUO,SAASM,EAAgBN,EAAkBzB,EAA8C,CAC9F,MAAMgC,EAAa,CAAE,GAAGpC,EAAgC,GAAGI,GAAS,aAAA,EAAgByB,CAAQ,EAC5F,OAAKO,EAGDA,EAAW,UACH7B,gBAAc,MAAMH,GAAS,QAAU,IAAM,GAAG,QAAQyB,CAAQ,GACnE,QACEO,EAAW,SAGfA,EAAW,SART,IASX,CAWO,SAASC,EAAkBC,EAAcT,EAAkBzB,EAAuC,CACvG,MAAMmC,EAAOJ,EAAgBN,EAAUzB,CAAO,EAC9C,OAAOmC,GAAQ,KAAOD,EAAOA,EAAK,QAAQvC,EAAYwC,CAAI,CAC5D"}
1
+ {"version":3,"file":"date-util-CZmiQEYH.cjs","sources":["../src/date-util.ts"],"sourcesContent":["import { ZonedDateTime } from './zoned-date-time';\n\n/**\n * 日時として解釈する値。string はISO形式または inputFormat の書式、number は epoch ミリ秒\n * ZonedDateTime は inputTimezone を省略した場合、その ZonedDateTime のタイムゾーンで扱う\n */\nexport type DateInput = string | Date | number | ZonedDateTime | null | undefined;\n\n/** 日時の切り捨て(startOf / endOf)に使う単位 */\nexport type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';\n\n/** 期間の単位 */\nexport type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'quarters' | 'years';\n\n/** 日時の加算・減算に使う期間。負の値で減算になる */\nexport interface Duration {\n years?: number;\n quarters?: number;\n months?: number;\n weeks?: number;\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n milliseconds?: number;\n}\n\n/**\n * 日時を解釈するときのオプション\n */\nexport interface ParseDateOptions {\n /** 入力の書式。配列の場合は先頭から順に試す。いずれにも一致しない場合はISO形式として解釈する */\n inputFormat?: string | string[];\n /** ゾーン情報を含まない入力をどのタイムゾーンの日時とみなすか(IANA名)。既定は 'UTC' */\n inputTimezone?: string;\n /** 解釈した日時に加算する期間。startOf / endOf より先に適用する */\n duration?: Duration;\n /** 指定した単位の最初の時点に切り捨てる(month なら月初の00:00:00.000) */\n startOf?: DateUnit;\n /** 指定した単位の最後の時点に切り上げる(month なら月末の23:59:59.999) */\n endOf?: DateUnit;\n /** 書式の月名・曜日名を解釈・出力するときのロケール。既定は 'en-US' */\n locale?: string;\n}\n\n/**\n * 日時を文字列にするときのオプション\n */\nexport interface FormatDateOptions extends ParseDateOptions {\n /** 出力の書式。省略時はISO形式 */\n outputFormat?: string;\n /** 出力に使うタイムゾーン(IANA名)。既定は 'UTC' */\n outputTimezone?: string;\n /** 日時として解釈できない値に対する出力。既定は 'Invalid Date' */\n invalidText?: string;\n}\n\n/** タイムゾーンの略称。夏時間のないタイムゾーンでは daylight を持たない */\nexport interface TimezoneAbbreviation {\n standard: string;\n daylight?: string;\n}\n\n/** IANA名をキーにしたタイムゾーンの略称の表 */\nexport type TimezoneAbbreviations = Record<string, TimezoneAbbreviation>;\n\n/**\n * タイムゾーンの略称を解決するときのオプション\n */\nexport interface TimezoneAbbrOptions {\n /** 夏時間かどうかを判定する時点。既定は現在時刻 */\n at?: Date;\n /** 既定の表に追加・上書きする略称 */\n abbreviations?: TimezoneAbbreviations;\n}\n\nconst DEFAULT_TIMEZONE = 'UTC';\n\nconst TIMESTAMP_FORMAT = `yyyy-MM-dd'T'HH:mm:ss.SSSZZ`;\n\n/** 1970-01-01 を表すExcelの日付シリアル値 */\nconst EXCEL_EPOCH_SERIAL = 25569;\n\nconst MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;\n\nconst MILLISECONDS_PER_HOUR = 60 * 60 * 1000;\n\nconst GMT_OFFSET = /GMT[+-]\\d{1,2}(:\\d{2})?/g;\n\n/**\n * 略称の既定の表。略称は世界で一意ではないため(CST は米国中部・中国などで使われる)、このライブラリが採用する表記である\n */\nconst DEFAULT_TIMEZONE_ABBREVIATIONS: TimezoneAbbreviations = {\n 'UTC': { standard: 'UTC' },\n 'Asia/Tokyo': { standard: 'JST' },\n 'Asia/Seoul': { standard: 'KST' },\n 'Asia/Shanghai': { standard: 'CST' },\n 'Asia/Hong_Kong': { standard: 'HKT' },\n 'Asia/Taipei': { standard: 'CST' },\n 'Asia/Singapore': { standard: 'SGT' },\n 'Asia/Manila': { standard: 'PHT' },\n 'Asia/Bangkok': { standard: 'ICT' },\n 'Asia/Ho_Chi_Minh': { standard: 'ICT' },\n 'Asia/Jakarta': { standard: 'WIB' },\n 'Asia/Kolkata': { standard: 'IST' },\n 'Asia/Dubai': { standard: 'GST' },\n 'Australia/Sydney': { standard: 'AEST', daylight: 'AEDT' },\n 'Pacific/Auckland': { standard: 'NZST', daylight: 'NZDT' },\n 'Europe/London': { standard: 'GMT', daylight: 'BST' },\n 'Europe/Paris': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Berlin': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Madrid': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Rome': { standard: 'CET', daylight: 'CEST' },\n 'Europe/Amsterdam': { standard: 'CET', daylight: 'CEST' },\n 'America/New_York': { standard: 'EST', daylight: 'EDT' },\n 'America/Toronto': { standard: 'EST', daylight: 'EDT' },\n 'America/Chicago': { standard: 'CST', daylight: 'CDT' },\n 'America/Denver': { standard: 'MST', daylight: 'MDT' },\n 'America/Phoenix': { standard: 'MST' },\n 'America/Los_Angeles': { standard: 'PST', daylight: 'PDT' },\n 'America/Vancouver': { standard: 'PST', daylight: 'PDT' },\n 'America/Mexico_City': { standard: 'CST' },\n 'America/Sao_Paulo': { standard: 'BRT' }\n};\n\nconst compare = (date1: DateInput, date2: DateInput, options: ParseDateOptions | undefined, predicate: (v1: number, v2: number) => boolean): boolean => {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return false;\n }\n return predicate(d1.toMillis(), d2.toMillis());\n};\n\n/**\n * 値を日時として解釈し、Date を返す\n * duration / startOf / endOf は inputTimezone のゾーンで計算する\n * 解釈できない値、null / undefined / 空文字は null を返す。タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {Date | null}\n */\nexport function parseDate(value: DateInput, options?: ParseDateOptions): Date | null {\n return ZonedDateTime.parse(value, options)?.toDate() ?? null;\n}\n\n/**\n * 値を日時として解釈し、outputTimezone での文字列にする\n * value を省略して options だけを渡した場合は現在時刻を整形する\n * null / undefined / 空文字は空文字を返す。解釈できない値は 'Invalid Date' を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {DateInput} value\n * @param {FormatDateOptions} [options]\n * @returns {string}\n */\nexport function formatDate(options: FormatDateOptions): string;\nexport function formatDate(value: DateInput, options?: FormatDateOptions): string;\nexport function formatDate(value: DateInput | FormatDateOptions, options?: FormatDateOptions): string {\n if (typeof value === 'object' && value !== null && !(value instanceof Date) && !(value instanceof ZonedDateTime)) {\n return formatDate(new Date(), value);\n }\n if (value == null || value === '') {\n return '';\n }\n const d = ZonedDateTime.parse(value, options);\n if (!d) {\n return options?.invalidText ?? 'Invalid Date';\n }\n const output = d.setZone(options?.outputTimezone ?? DEFAULT_TIMEZONE);\n return options?.outputFormat ? output.format(options.outputFormat, { locale: options.locale }) : output.toISO();\n}\n\n/**\n * 値が日時として解釈できるか判定する\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isValid(value: DateInput, options?: ParseDateOptions): boolean {\n return ZonedDateTime.parse(value, options) != null;\n}\n\n/**\n * date1 と date2 が同じ時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSame(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 === v2);\n}\n\n/**\n * date1 が date2 より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 < v2);\n}\n\n/**\n * date1 が date2 と同じか、より前の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrBefore(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v1 <= v2);\n}\n\n/**\n * date1 が date2 より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 < v1);\n}\n\n/**\n * date1 が date2 と同じか、より後の時刻か判定する。どちらかが解釈できない場合は false\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {boolean}\n */\nexport function isSameOrAfter(date1: DateInput, date2: DateInput, options?: ParseDateOptions): boolean {\n return compare(date1, date2, options, (v1, v2) => v2 <= v1);\n}\n\n/**\n * 値が inputTimezone での今日より前の日付か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDate(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options)?.startOf('day');\n if (!target) {\n return false;\n }\n const today = ZonedDateTime.now(target.timezone).startOf('day');\n return target.lt(today);\n}\n\n/**\n * 値が現在時刻より前か判定する。解釈できない場合は false\n *\n * @param {DateInput} value\n * @param {ParseDateOptions} [options]\n * @returns {boolean}\n */\nexport function isPastDateTime(value: DateInput, options?: ParseDateOptions): boolean {\n const target = ZonedDateTime.parse(value, options);\n return target != null && target.toMillis() < Date.now();\n}\n\n/**\n * date1 − date2 を unit の単位で返す\n * 両方を inputTimezone で unit の始まりに切り捨ててから差を取るため、暦の上での差になる(23:00 と翌 01:00 の days は 1)\n * どちらかが解釈できない場合は NaN を返す\n *\n * @param {DateInput} date1\n * @param {DateInput} date2\n * @param {TimeUnit} unit\n * @param {ParseDateOptions} [options] 両方の値に適用する\n * @returns {number}\n */\nexport function diff(date1: DateInput, date2: DateInput, unit: TimeUnit, options?: ParseDateOptions): number {\n const d1 = ZonedDateTime.parse(date1, options);\n const d2 = ZonedDateTime.parse(date2, options);\n if (!d1 || !d2) {\n return NaN;\n }\n return d1.diff(d2, unit);\n}\n\n/**\n * 現在時刻を timezone での 'yyyy-MM-ddTHH:mm:ss.SSS+HH:mm' 形式の文字列で返す\n *\n * @param {string} [timezone] IANA名。既定は 'UTC'\n * @returns {string}\n */\nexport function currentTimestamp(timezone: string = DEFAULT_TIMEZONE): string {\n return ZonedDateTime.now(timezone).format(TIMESTAMP_FORMAT);\n}\n\n/**\n * Excelの日付シリアル値を epoch ミリ秒に変換する\n * Excelの日付シリアル値はゾーンの概念を持たないため、そのままではUTCの日時として変換される\n * シリアル値がどのゾーンの日時かが分かっている場合は offset に時間差を指定する\n *\n * @example\n * convertExcelDateSerialToUnixTimeSerial(45200); // 1696118400000 (2023-10-01T00:00:00Z)\n * convertExcelDateSerialToUnixTimeSerial(45200, { offset: 9 }); // 1696086000000 (2023-10-01T00:00:00+09:00)\n *\n * @param {number} excelDateSerial\n * @param {*} [options]\n * └ offset シリアル値のゾーンのUTCからの時間差(時)\n * @returns {number}\n */\nexport function convertExcelDateSerialToUnixTimeSerial(excelDateSerial: number, options?: {\n offset: number;\n}): number {\n let timeserial = (excelDateSerial - EXCEL_EPOCH_SERIAL) * MILLISECONDS_PER_DAY;\n if (options?.offset) {\n timeserial -= options.offset * MILLISECONDS_PER_HOUR;\n }\n return timeserial;\n}\n\n/**\n * timezone が at の時点で夏時間かどうかを返す\n * at を省略した場合は現在時刻で判定する。at が解釈できない場合は false を返す\n * タイムゾーンの指定が不正な場合は RangeError をスローする\n *\n * @param {string} timezone IANA名\n * @param {DateInput} [at] 判定する時点\n * @returns {boolean}\n */\nexport function isInDST(timezone: string, at?: DateInput): boolean {\n const d = at === undefined ? ZonedDateTime.now(timezone) : ZonedDateTime.parse(at)?.setZone(timezone);\n return d?.isInDST ?? false;\n}\n\n/**\n * タイムゾーンの略称を返す。夏時間の期間中は夏時間の略称を返す\n * 既定の表にない場合は null を返す。表は options.abbreviations で追加・上書きできる\n *\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string | null}\n */\nexport function getTimezoneAbbr(timezone: string, options?: TimezoneAbbrOptions): string | null {\n const definition = { ...DEFAULT_TIMEZONE_ABBREVIATIONS, ...options?.abbreviations }[timezone];\n if (!definition) {\n return null;\n }\n if (definition.daylight) {\n const d = ZonedDateTime.parse(options?.at ?? new Date())?.setZone(timezone);\n if (d?.isInDST) {\n return definition.daylight;\n }\n }\n return definition.standard;\n}\n\n/**\n * 文字列中の 'GMT+9' のようなオフセット表記を、timezone の略称に置き換える\n * 略称が解決できない場合は文字列をそのまま返す\n *\n * @param {string} text\n * @param {string} timezone IANA名\n * @param {TimezoneAbbrOptions} [options]\n * @returns {string}\n */\nexport function applyTimezoneAbbr(text: string, timezone: string, options?: TimezoneAbbrOptions): string {\n const abbr = getTimezoneAbbr(timezone, options);\n return abbr == null ? text : text.replace(GMT_OFFSET, abbr);\n}\n"],"names":["DEFAULT_TIMEZONE","TIMESTAMP_FORMAT","EXCEL_EPOCH_SERIAL","MILLISECONDS_PER_DAY","MILLISECONDS_PER_HOUR","GMT_OFFSET","DEFAULT_TIMEZONE_ABBREVIATIONS","compare","date1","date2","options","predicate","d1","ZonedDateTime","d2","parseDate","value","formatDate","d","output","isValid","isSame","v1","v2","isBefore","isSameOrBefore","isAfter","isSameOrAfter","isPastDate","target","today","isPastDateTime","diff","unit","currentTimestamp","timezone","convertExcelDateSerialToUnixTimeSerial","excelDateSerial","timeserial","isInDST","at","getTimezoneAbbr","definition","applyTimezoneAbbr","text","abbr"],"mappings":"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"}
@@ -7,7 +7,7 @@ export type DateInput = string | Date | number | ZonedDateTime | null | undefine
7
7
  /** 日時の切り捨て(startOf / endOf)に使う単位 */
8
8
  export type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';
9
9
  /** 期間の単位 */
10
- export type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';
10
+ export type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'quarters' | 'years';
11
11
  /** 日時の加算・減算に使う期間。負の値で減算になる */
12
12
  export interface Duration {
13
13
  years?: number;
@@ -7,7 +7,7 @@ export type DateInput = string | Date | number | ZonedDateTime | null | undefine
7
7
  /** 日時の切り捨て(startOf / endOf)に使う単位 */
8
8
  export type DateUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';
9
9
  /** 期間の単位 */
10
- export type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years';
10
+ export type TimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'quarters' | 'years';
11
11
  /** 日時の加算・減算に使う期間。負の値で減算になる */
12
12
  export interface Duration {
13
13
  years?: number;
package/lib/decimal.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("big.js"),o={roundDown:0,roundHalfUp:1,roundHalfEven:2,roundUp:3},b=20,g=/^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i,n=u.Big();n.DP=b;n.RM=o.roundHalfUp;const s=e=>e==null||e===""||typeof e=="number"&&Number.isNaN(e);class t{static ROUNDING_MODE=o;big;constructor(r){this.big=t.toBig(r)}static toBig(r){if(s(r))return n(0);if(r instanceof t)return r.big;switch(typeof r){case"number":if(!Number.isFinite(r))throw new TypeError(`Invalid number: ${r}`);return n(r);case"bigint":return n(r.toString());default:{const i=r.trim();if(!g.test(i))throw new TypeError(`Invalid number: ${r}`);return n(i.replace(/^\+/,""))}}}static wrap(r){const i=new t(0);return i.big=r,i}add(r){return t.wrap(this.big.add(t.toBig(r)))}sub(r){return t.wrap(this.big.sub(t.toBig(r)))}times(r){return t.wrap(this.big.times(t.toBig(r)))}div(r){if(s(r))return t.wrap(this.big);const i=t.toBig(r);if(i.eq(0))throw new RangeError("Division by zero");return t.wrap(this.big.div(i))}round(r=0,i=o.roundHalfUp){return t.wrap(this.big.round(r,i))}abs(){return t.wrap(this.big.abs())}compareTo(r){return this.big.cmp(t.toBig(r))}eq(r){return this.compareTo(r)===0}lt(r){return this.compareTo(r)<0}lte(r){return this.compareTo(r)<=0}gt(r){return 0<this.compareTo(r)}gte(r){return 0<=this.compareTo(r)}toNumber(){return this.big.toNumber()}toFixed(r,i=o.roundHalfUp){return this.big.round(r,i).toFixed(r)}toString(){return this.big.toFixed()}}exports.Decimal=t;exports.ROUNDING_MODE=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("big.js"),o={roundDown:0,roundHalfUp:1,roundHalfEven:2,roundUp:3},b=20,g=/^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i,n=u.Big();n.DP=b;n.RM=o.roundHalfUp;const s=e=>e==null||e===""||typeof e=="number"&&Number.isNaN(e);class t{static ROUNDING_MODE=o;big;constructor(r){this.big=t.toBig(r)}static toBig(r){if(s(r))return n(0);if(r instanceof t)return r.big;switch(typeof r){case"number":if(!Number.isFinite(r))throw new TypeError(`Invalid number: ${r}`);return n(r);case"bigint":return n(r.toString());default:{const i=r.trim();if(!g.test(i))throw new TypeError(`Invalid number: ${r}`);return n(i.replace(/^\+/,""))}}}static wrap(r){const i=new t(0);return i.big=r,i}add(r){return t.wrap(this.big.add(t.toBig(r)))}sub(r){return t.wrap(this.big.sub(t.toBig(r)))}times(r){return t.wrap(this.big.times(t.toBig(r)))}div(r){if(s(r))return t.wrap(this.big);const i=t.toBig(r);if(i.eq(0))throw new RangeError("Division by zero");return t.wrap(this.big.div(i))}round(r=0,i=o.roundHalfUp){return t.wrap(this.big.round(r,i))}abs(){return t.wrap(this.big.abs())}compareTo(r){return this.big.cmp(t.toBig(r))}eq(r){return this.compareTo(r)===0}lt(r){return this.compareTo(r)<0}lte(r){return this.compareTo(r)<=0}gt(r){return 0<this.compareTo(r)}gte(r){return 0<=this.compareTo(r)}toNumber(){return this.big.toNumber()}toFixed(r,i=o.roundHalfUp){return this.big.toFixed(r,i)}toString(){return this.big.toFixed()}}exports.Decimal=t;exports.ROUNDING_MODE=o;
2
2
  //# sourceMappingURL=decimal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"decimal.cjs","sources":["../src/decimal.ts"],"sourcesContent":["/**\n * このクラス Decimal の役割は、算術演算の実体としての Big を内部に閉じ込め、利用者側に露出させないことにある。\n * 2026-10-08時点では big.js に依存しているが、将来的に演算演算のライブラリを変更した場合に\n * 安全・簡単に移行できることを目的としている。\n */\nimport { Big } from 'big.js';\n\n/**\n * 数値として扱える値の型\n */\nexport type NumberSource = number | string | bigint | Decimal;\n\n/**\n * 丸めモード\n */\nexport const ROUNDING_MODE = {\n /**\n * Rounds towards zero.\n * I.e. truncate, no rounding.\n */\n roundDown: 0,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds away from zero.\n */\n roundHalfUp: 1,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds towards even neighbour.\n */\n roundHalfEven: 2,\n /**\n * Rounds away from zero.\n */\n roundUp: 3\n} as const;\n\nexport type RoundingMode = typeof ROUNDING_MODE[keyof typeof ROUNDING_MODE];\n\n/**\n * Decimalの生成・演算に渡せる値の型\n * null/undefined/空文字/NaNは0とみなす(divの割る値は1とみなす)\n */\nexport type DecimalSource = NumberSource | null | undefined;\n\n/** 除算で保持する小数桁数 */\nconst DIVISION_SCALE = 20;\n\n/** 数値として解釈できる文字列のパターン(符号・小数点・指数表記) */\nconst NUMERIC_STRING_PATTERN = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n// 独立したコンストラクタにすることで、利用側がグローバルの Big.DP / Big.RM を書き換えても影響を受けないようにする\nconst BigNumber = Big();\nBigNumber.DP = DIVISION_SCALE;\nBigNumber.RM = ROUNDING_MODE.roundHalfUp;\n\n// null/undefined/空文字/NaNはtrueを返す\nconst isEmpty = (value: DecimalSource): value is null | undefined | '' => value == null || value === '' || (typeof value === 'number' && Number.isNaN(value));\n\n/**\n * 任意精度の10進数を表す不変オブジェクト\n * 演算メソッドは自身を変更せず、結果を新しいインスタンスで返す\n * 除算は小数20桁(roundHalfUp)まで保持し、それ以降の桁は切り捨てではなく丸める\n */\nexport class Decimal {\n /** 丸めモード */\n public static readonly ROUNDING_MODE = ROUNDING_MODE;\n\n /**\n * 算術演算インスタンス\n */\n private big: Big;\n\n /**\n * @param {DecimalSource} value 数値、数値文字列、bigint、Decimal\n * null/undefined/空文字/NaNは0とみなす\n * 数値として解釈できない文字列・Infinityは TypeError をスローする\n */\n constructor(value: DecimalSource) {\n this.big = Decimal.toBig(value);\n }\n\n private static toBig(value: DecimalSource): Big {\n if (isEmpty(value)) {\n return BigNumber(0);\n }\n if (value instanceof Decimal) {\n return value.big;\n }\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n return BigNumber(value);\n case 'bigint':\n return BigNumber(value.toString());\n default: {\n const trimmed = value.trim();\n if (!NUMERIC_STRING_PATTERN.test(trimmed)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n // 先頭の '+' は数値として解釈できる表記だが、内部の算術ライブラリが受け付けないため取り除く\n return BigNumber(trimmed.replace(/^\\+/, ''));\n }\n }\n }\n\n private static wrap(big: Big): Decimal {\n const decimal = new Decimal(0);\n decimal.big = big;\n return decimal;\n }\n\n /**\n * 加算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public add(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.add(Decimal.toBig(value)));\n }\n\n /**\n * 減算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public sub(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.sub(Decimal.toBig(value)));\n }\n\n /**\n * 乗算した結果を返す\n * null/undefined/空文字/NaNは0とみなすため、結果は0になる\n * 元の値を保持したい場合は times(discount ?? 1) のようにフォールバック値を指定する\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public times(value: DecimalSource): Decimal {\n // 掛ける値が空のとき、0とみなすべきか元の値を保持すべきかは計算対象によって異なる\n // 手数料 x 件数: 件数が未定義なら総額は0が適切\n // 商品価格 x 割引率: 割引率が未定義なら元の価格が適切\n // 1とみなすと、new Decimal(null).times(3) は 0、new Decimal(3).times(null) は 3 になり、引数の順序で結果が変わる\n // そのため常に0とみなし、元の値を保持したい場合は呼び出し側でフォールバック値を指定する\n return Decimal.wrap(this.big.times(Decimal.toBig(value)));\n }\n\n /**\n * 除算した結果を返す\n * 結果は小数20桁(roundHalfUp)まで保持する\n * 割る値のnull/undefined/空文字/NaNは1とみなすため、結果は元の値と同じになる\n * 割る値に0を指定した場合は RangeError をスローする\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public div(value: DecimalSource): Decimal {\n // 割る値が空のとき、0とみなすとすべてゼロ除算エラーになり計算が成り立たないため1とみなす\n if (isEmpty(value)) {\n return Decimal.wrap(this.big);\n }\n const divisor = Decimal.toBig(value);\n if (divisor.eq(0)) {\n throw new RangeError('Division by zero');\n }\n return Decimal.wrap(this.big.div(divisor));\n }\n\n /**\n * 指定した小数桁で丸めた結果を返す\n * 負の桁数を指定すると整数部を丸める(-2 なら百の位)\n *\n * @param {number} [scale] 小数桁数 デフォルトは0\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {Decimal}\n */\n public round(scale: number = 0, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): Decimal {\n return Decimal.wrap(this.big.round(scale, roundingMode));\n }\n\n /**\n * 絶対値を返す\n *\n * @returns {Decimal}\n */\n public abs(): Decimal {\n return Decimal.wrap(this.big.abs());\n }\n\n /**\n * 値を比較する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {-1 | 0 | 1} 自身が小さければ-1、等しければ0、大きければ1\n */\n public compareTo(value: DecimalSource): -1 | 0 | 1 {\n return this.big.cmp(Decimal.toBig(value));\n }\n\n /**\n * 等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public eq(value: DecimalSource): boolean {\n return this.compareTo(value) === 0;\n }\n\n /**\n * 自身が小さいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lt(value: DecimalSource): boolean {\n return this.compareTo(value) < 0;\n }\n\n /**\n * 自身が小さいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lte(value: DecimalSource): boolean {\n return this.compareTo(value) <= 0;\n }\n\n /**\n * 自身が大きいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gt(value: DecimalSource): boolean {\n return 0 < this.compareTo(value);\n }\n\n /**\n * 自身が大きいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gte(value: DecimalSource): boolean {\n return 0 <= this.compareTo(value);\n }\n\n /**\n * numberに変換する\n * Number.MAX_SAFE_INTEGERを超える値や、numberで表現できない桁数の小数は精度が落ちる\n *\n * @returns {number}\n */\n public toNumber(): number {\n return this.big.toNumber();\n }\n\n /**\n * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n * 丸めた結果が0になる場合は符号を付けない\n *\n * @param {number} scale 小数桁数\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n */\n public toFixed(scale: number, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): string {\n return this.big.round(scale, roundingMode).toFixed(scale);\n }\n\n /**\n * 文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n *\n * @returns {string}\n */\n public toString(): string {\n return this.big.toFixed();\n }\n}\n"],"names":["ROUNDING_MODE","DIVISION_SCALE","NUMERIC_STRING_PATTERN","BigNumber","Big","isEmpty","value","Decimal","trimmed","big","decimal","divisor","scale","roundingMode"],"mappings":"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"}
1
+ {"version":3,"file":"decimal.cjs","sources":["../src/decimal.ts"],"sourcesContent":["/**\n * このクラス Decimal の役割は、算術演算の実体としての Big を内部に閉じ込め、利用者側に露出させないことにある。\n * 2026-10-08時点では big.js に依存しているが、将来的に演算演算のライブラリを変更した場合に\n * 安全・簡単に移行できることを目的としている。\n */\nimport { Big } from 'big.js';\n\n/**\n * 数値として扱える値の型\n */\nexport type NumberSource = number | string | bigint | Decimal;\n\n/**\n * 丸めモード\n */\nexport const ROUNDING_MODE = {\n /**\n * Rounds towards zero.\n * I.e. truncate, no rounding.\n */\n roundDown: 0,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds away from zero.\n */\n roundHalfUp: 1,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds towards even neighbour.\n */\n roundHalfEven: 2,\n /**\n * Rounds away from zero.\n */\n roundUp: 3\n} as const;\n\nexport type RoundingMode = typeof ROUNDING_MODE[keyof typeof ROUNDING_MODE];\n\n/**\n * Decimalの生成・演算に渡せる値の型\n * null/undefined/空文字/NaNは0とみなす(divの割る値は1とみなす)\n */\nexport type DecimalSource = NumberSource | null | undefined;\n\n/** 除算で保持する小数桁数 */\nconst DIVISION_SCALE = 20;\n\n/** 数値として解釈できる文字列のパターン(符号・小数点・指数表記) */\nconst NUMERIC_STRING_PATTERN = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n// 独立したコンストラクタにすることで、利用側がグローバルの Big.DP / Big.RM を書き換えても影響を受けないようにする\nconst BigNumber = Big();\nBigNumber.DP = DIVISION_SCALE;\nBigNumber.RM = ROUNDING_MODE.roundHalfUp;\n\n// null/undefined/空文字/NaNはtrueを返す\nconst isEmpty = (value: DecimalSource): value is null | undefined | '' => value == null || value === '' || (typeof value === 'number' && Number.isNaN(value));\n\n/**\n * 任意精度の10進数を表す不変オブジェクト\n * 演算メソッドは自身を変更せず、結果を新しいインスタンスで返す\n * 除算は小数20桁(roundHalfUp)まで保持し、それ以降の桁は切り捨てではなく丸める\n */\nexport class Decimal {\n /** 丸めモード */\n public static readonly ROUNDING_MODE = ROUNDING_MODE;\n\n /**\n * 算術演算インスタンス\n */\n private big: Big;\n\n /**\n * @param {DecimalSource} value 数値、数値文字列、bigint、Decimal\n * null/undefined/空文字/NaNは0とみなす\n * 数値として解釈できない文字列・Infinityは TypeError をスローする\n */\n constructor(value: DecimalSource) {\n this.big = Decimal.toBig(value);\n }\n\n private static toBig(value: DecimalSource): Big {\n if (isEmpty(value)) {\n return BigNumber(0);\n }\n if (value instanceof Decimal) {\n return value.big;\n }\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n return BigNumber(value);\n case 'bigint':\n return BigNumber(value.toString());\n default: {\n const trimmed = value.trim();\n if (!NUMERIC_STRING_PATTERN.test(trimmed)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n // 先頭の '+' は数値として解釈できる表記だが、内部の算術ライブラリが受け付けないため取り除く\n return BigNumber(trimmed.replace(/^\\+/, ''));\n }\n }\n }\n\n private static wrap(big: Big): Decimal {\n const decimal = new Decimal(0);\n decimal.big = big;\n return decimal;\n }\n\n /**\n * 加算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public add(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.add(Decimal.toBig(value)));\n }\n\n /**\n * 減算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public sub(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.sub(Decimal.toBig(value)));\n }\n\n /**\n * 乗算した結果を返す\n * null/undefined/空文字/NaNは0とみなすため、結果は0になる\n * 元の値を保持したい場合は times(discount ?? 1) のようにフォールバック値を指定する\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public times(value: DecimalSource): Decimal {\n // 掛ける値が空のとき、0とみなすべきか元の値を保持すべきかは計算対象によって異なる\n // 手数料 x 件数: 件数が未定義なら総額は0が適切\n // 商品価格 x 割引率: 割引率が未定義なら元の価格が適切\n // 1とみなすと、new Decimal(null).times(3) は 0、new Decimal(3).times(null) は 3 になり、引数の順序で結果が変わる\n // そのため常に0とみなし、元の値を保持したい場合は呼び出し側でフォールバック値を指定する\n return Decimal.wrap(this.big.times(Decimal.toBig(value)));\n }\n\n /**\n * 除算した結果を返す\n * 結果は小数20桁(roundHalfUp)まで保持する\n * 割る値のnull/undefined/空文字/NaNは1とみなすため、結果は元の値と同じになる\n * 割る値に0を指定した場合は RangeError をスローする\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public div(value: DecimalSource): Decimal {\n // 割る値が空のとき、0とみなすとすべてゼロ除算エラーになり計算が成り立たないため1とみなす\n if (isEmpty(value)) {\n return Decimal.wrap(this.big);\n }\n const divisor = Decimal.toBig(value);\n if (divisor.eq(0)) {\n throw new RangeError('Division by zero');\n }\n return Decimal.wrap(this.big.div(divisor));\n }\n\n /**\n * 指定した小数桁で丸めた結果を返す\n * 負の桁数を指定すると整数部を丸める(-2 なら百の位)\n *\n * @param {number} [scale] 小数桁数 デフォルトは0\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {Decimal}\n */\n public round(scale: number = 0, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): Decimal {\n return Decimal.wrap(this.big.round(scale, roundingMode));\n }\n\n /**\n * 絶対値を返す\n *\n * @returns {Decimal}\n */\n public abs(): Decimal {\n return Decimal.wrap(this.big.abs());\n }\n\n /**\n * 値を比較する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {-1 | 0 | 1} 自身が小さければ-1、等しければ0、大きければ1\n */\n public compareTo(value: DecimalSource): -1 | 0 | 1 {\n return this.big.cmp(Decimal.toBig(value));\n }\n\n /**\n * 等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public eq(value: DecimalSource): boolean {\n return this.compareTo(value) === 0;\n }\n\n /**\n * 自身が小さいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lt(value: DecimalSource): boolean {\n return this.compareTo(value) < 0;\n }\n\n /**\n * 自身が小さいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lte(value: DecimalSource): boolean {\n return this.compareTo(value) <= 0;\n }\n\n /**\n * 自身が大きいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gt(value: DecimalSource): boolean {\n return 0 < this.compareTo(value);\n }\n\n /**\n * 自身が大きいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gte(value: DecimalSource): boolean {\n return 0 <= this.compareTo(value);\n }\n\n /**\n * numberに変換する\n * Number.MAX_SAFE_INTEGERを超える値や、numberで表現できない桁数の小数は精度が落ちる\n *\n * @returns {number}\n */\n public toNumber(): number {\n return this.big.toNumber();\n }\n\n /**\n * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n * ゼロでない値を丸めて0になる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')\n *\n * @param {number} scale 小数桁数\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n */\n public toFixed(scale: number, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): string {\n return this.big.toFixed(scale, roundingMode);\n }\n\n /**\n * 文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n *\n * @returns {string}\n */\n public toString(): string {\n return this.big.toFixed();\n }\n}\n"],"names":["ROUNDING_MODE","DIVISION_SCALE","NUMERIC_STRING_PATTERN","BigNumber","Big","isEmpty","value","Decimal","trimmed","big","decimal","divisor","scale","roundingMode"],"mappings":"0GAeaA,EAAgB,CAK3B,UAAW,EAKX,YAAa,EAKb,cAAe,EAIf,QAAS,CACX,EAWMC,EAAiB,GAGjBC,EAAyB,wCAGzBC,EAAYC,EAAAA,IAAA,EAClBD,EAAU,GAAKF,EACfE,EAAU,GAAKH,EAAc,YAG7B,MAAMK,EAAWC,GAAyDA,GAAS,MAAQA,IAAU,IAAO,OAAOA,GAAU,UAAY,OAAO,MAAMA,CAAK,EAOpJ,MAAMC,CAAQ,CAEnB,OAAuB,cAAgBP,EAK/B,IAOR,YAAYM,EAAsB,CAChC,KAAK,IAAMC,EAAQ,MAAMD,CAAK,CAChC,CAEA,OAAe,MAAMA,EAA2B,CAC9C,GAAID,EAAQC,CAAK,EACf,OAAOH,EAAU,CAAC,EAEpB,GAAIG,aAAiBC,EACnB,OAAOD,EAAM,IAEf,OAAQ,OAAOA,EAAA,CACb,IAAK,SACH,GAAI,CAAC,OAAO,SAASA,CAAK,EACxB,MAAM,IAAI,UAAU,mBAAmBA,CAAK,EAAE,EAEhD,OAAOH,EAAUG,CAAK,EACxB,IAAK,SACH,OAAOH,EAAUG,EAAM,UAAU,EACnC,QAAS,CACP,MAAME,EAAUF,EAAM,KAAA,EACtB,GAAI,CAACJ,EAAuB,KAAKM,CAAO,EACtC,MAAM,IAAI,UAAU,mBAAmBF,CAAK,EAAE,EAGhD,OAAOH,EAAUK,EAAQ,QAAQ,MAAO,EAAE,CAAC,CAC7C,CAAA,CAEJ,CAEA,OAAe,KAAKC,EAAmB,CACrC,MAAMC,EAAU,IAAIH,EAAQ,CAAC,EAC7B,OAAAG,EAAQ,IAAMD,EACPC,CACT,CASO,IAAIJ,EAA+B,CACxC,OAAOC,EAAQ,KAAK,KAAK,IAAI,IAAIA,EAAQ,MAAMD,CAAK,CAAC,CAAC,CACxD,CASO,IAAIA,EAA+B,CACxC,OAAOC,EAAQ,KAAK,KAAK,IAAI,IAAIA,EAAQ,MAAMD,CAAK,CAAC,CAAC,CACxD,CAUO,MAAMA,EAA+B,CAM1C,OAAOC,EAAQ,KAAK,KAAK,IAAI,MAAMA,EAAQ,MAAMD,CAAK,CAAC,CAAC,CAC1D,CAWO,IAAIA,EAA+B,CAExC,GAAID,EAAQC,CAAK,EACf,OAAOC,EAAQ,KAAK,KAAK,GAAG,EAE9B,MAAMI,EAAUJ,EAAQ,MAAMD,CAAK,EACnC,GAAIK,EAAQ,GAAG,CAAC,EACd,MAAM,IAAI,WAAW,kBAAkB,EAEzC,OAAOJ,EAAQ,KAAK,KAAK,IAAI,IAAII,CAAO,CAAC,CAC3C,CAUO,MAAMC,EAAgB,EAAGC,EAA6Bb,EAAc,YAAsB,CAC/F,OAAOO,EAAQ,KAAK,KAAK,IAAI,MAAMK,EAAOC,CAAY,CAAC,CACzD,CAOO,KAAe,CACpB,OAAON,EAAQ,KAAK,KAAK,IAAI,KAAK,CACpC,CASO,UAAUD,EAAkC,CACjD,OAAO,KAAK,IAAI,IAAIC,EAAQ,MAAMD,CAAK,CAAC,CAC1C,CASO,GAAGA,EAA+B,CACvC,OAAO,KAAK,UAAUA,CAAK,IAAM,CACnC,CASO,GAAGA,EAA+B,CACvC,OAAO,KAAK,UAAUA,CAAK,EAAI,CACjC,CASO,IAAIA,EAA+B,CACxC,OAAO,KAAK,UAAUA,CAAK,GAAK,CAClC,CASO,GAAGA,EAA+B,CACvC,MAAO,GAAI,KAAK,UAAUA,CAAK,CACjC,CASO,IAAIA,EAA+B,CACxC,MAAO,IAAK,KAAK,UAAUA,CAAK,CAClC,CAQO,UAAmB,CACxB,OAAO,KAAK,IAAI,SAAA,CAClB,CAWO,QAAQM,EAAeC,EAA6Bb,EAAc,YAAqB,CAC5F,OAAO,KAAK,IAAI,QAAQY,EAAOC,CAAY,CAC7C,CAQO,UAAmB,CACxB,OAAO,KAAK,IAAI,QAAA,CAClB,CACF"}
package/lib/decimal.d.cts CHANGED
@@ -180,7 +180,7 @@ export declare class Decimal {
180
180
  /**
181
181
  * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する
182
182
  * 指数表記にはならず、通常の表記で返す
183
- * 丸めた結果が0になる場合は符号を付けない
183
+ * ゼロでない値を丸めて0になる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')
184
184
  *
185
185
  * @param {number} scale 小数桁数
186
186
  * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)
package/lib/decimal.d.ts CHANGED
@@ -180,7 +180,7 @@ export declare class Decimal {
180
180
  /**
181
181
  * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する
182
182
  * 指数表記にはならず、通常の表記で返す
183
- * 丸めた結果が0になる場合は符号を付けない
183
+ * ゼロでない値を丸めて0になる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')
184
184
  *
185
185
  * @param {number} scale 小数桁数
186
186
  * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)
package/lib/decimal.js CHANGED
@@ -201,14 +201,14 @@ class t {
201
201
  /**
202
202
  * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する
203
203
  * 指数表記にはならず、通常の表記で返す
204
- * 丸めた結果が0になる場合は符号を付けない
204
+ * ゼロでない値を丸めて0になる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')
205
205
  *
206
206
  * @param {number} scale 小数桁数
207
207
  * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)
208
208
  * @returns {string}
209
209
  */
210
210
  toFixed(r, i = s.roundHalfUp) {
211
- return this.big.round(r, i).toFixed(r);
211
+ return this.big.toFixed(r, i);
212
212
  }
213
213
  /**
214
214
  * 文字列に変換する
@@ -1 +1 @@
1
- {"version":3,"file":"decimal.js","sources":["../src/decimal.ts"],"sourcesContent":["/**\n * このクラス Decimal の役割は、算術演算の実体としての Big を内部に閉じ込め、利用者側に露出させないことにある。\n * 2026-10-08時点では big.js に依存しているが、将来的に演算演算のライブラリを変更した場合に\n * 安全・簡単に移行できることを目的としている。\n */\nimport { Big } from 'big.js';\n\n/**\n * 数値として扱える値の型\n */\nexport type NumberSource = number | string | bigint | Decimal;\n\n/**\n * 丸めモード\n */\nexport const ROUNDING_MODE = {\n /**\n * Rounds towards zero.\n * I.e. truncate, no rounding.\n */\n roundDown: 0,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds away from zero.\n */\n roundHalfUp: 1,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds towards even neighbour.\n */\n roundHalfEven: 2,\n /**\n * Rounds away from zero.\n */\n roundUp: 3\n} as const;\n\nexport type RoundingMode = typeof ROUNDING_MODE[keyof typeof ROUNDING_MODE];\n\n/**\n * Decimalの生成・演算に渡せる値の型\n * null/undefined/空文字/NaNは0とみなす(divの割る値は1とみなす)\n */\nexport type DecimalSource = NumberSource | null | undefined;\n\n/** 除算で保持する小数桁数 */\nconst DIVISION_SCALE = 20;\n\n/** 数値として解釈できる文字列のパターン(符号・小数点・指数表記) */\nconst NUMERIC_STRING_PATTERN = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n// 独立したコンストラクタにすることで、利用側がグローバルの Big.DP / Big.RM を書き換えても影響を受けないようにする\nconst BigNumber = Big();\nBigNumber.DP = DIVISION_SCALE;\nBigNumber.RM = ROUNDING_MODE.roundHalfUp;\n\n// null/undefined/空文字/NaNはtrueを返す\nconst isEmpty = (value: DecimalSource): value is null | undefined | '' => value == null || value === '' || (typeof value === 'number' && Number.isNaN(value));\n\n/**\n * 任意精度の10進数を表す不変オブジェクト\n * 演算メソッドは自身を変更せず、結果を新しいインスタンスで返す\n * 除算は小数20桁(roundHalfUp)まで保持し、それ以降の桁は切り捨てではなく丸める\n */\nexport class Decimal {\n /** 丸めモード */\n public static readonly ROUNDING_MODE = ROUNDING_MODE;\n\n /**\n * 算術演算インスタンス\n */\n private big: Big;\n\n /**\n * @param {DecimalSource} value 数値、数値文字列、bigint、Decimal\n * null/undefined/空文字/NaNは0とみなす\n * 数値として解釈できない文字列・Infinityは TypeError をスローする\n */\n constructor(value: DecimalSource) {\n this.big = Decimal.toBig(value);\n }\n\n private static toBig(value: DecimalSource): Big {\n if (isEmpty(value)) {\n return BigNumber(0);\n }\n if (value instanceof Decimal) {\n return value.big;\n }\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n return BigNumber(value);\n case 'bigint':\n return BigNumber(value.toString());\n default: {\n const trimmed = value.trim();\n if (!NUMERIC_STRING_PATTERN.test(trimmed)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n // 先頭の '+' は数値として解釈できる表記だが、内部の算術ライブラリが受け付けないため取り除く\n return BigNumber(trimmed.replace(/^\\+/, ''));\n }\n }\n }\n\n private static wrap(big: Big): Decimal {\n const decimal = new Decimal(0);\n decimal.big = big;\n return decimal;\n }\n\n /**\n * 加算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public add(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.add(Decimal.toBig(value)));\n }\n\n /**\n * 減算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public sub(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.sub(Decimal.toBig(value)));\n }\n\n /**\n * 乗算した結果を返す\n * null/undefined/空文字/NaNは0とみなすため、結果は0になる\n * 元の値を保持したい場合は times(discount ?? 1) のようにフォールバック値を指定する\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public times(value: DecimalSource): Decimal {\n // 掛ける値が空のとき、0とみなすべきか元の値を保持すべきかは計算対象によって異なる\n // 手数料 x 件数: 件数が未定義なら総額は0が適切\n // 商品価格 x 割引率: 割引率が未定義なら元の価格が適切\n // 1とみなすと、new Decimal(null).times(3) は 0、new Decimal(3).times(null) は 3 になり、引数の順序で結果が変わる\n // そのため常に0とみなし、元の値を保持したい場合は呼び出し側でフォールバック値を指定する\n return Decimal.wrap(this.big.times(Decimal.toBig(value)));\n }\n\n /**\n * 除算した結果を返す\n * 結果は小数20桁(roundHalfUp)まで保持する\n * 割る値のnull/undefined/空文字/NaNは1とみなすため、結果は元の値と同じになる\n * 割る値に0を指定した場合は RangeError をスローする\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public div(value: DecimalSource): Decimal {\n // 割る値が空のとき、0とみなすとすべてゼロ除算エラーになり計算が成り立たないため1とみなす\n if (isEmpty(value)) {\n return Decimal.wrap(this.big);\n }\n const divisor = Decimal.toBig(value);\n if (divisor.eq(0)) {\n throw new RangeError('Division by zero');\n }\n return Decimal.wrap(this.big.div(divisor));\n }\n\n /**\n * 指定した小数桁で丸めた結果を返す\n * 負の桁数を指定すると整数部を丸める(-2 なら百の位)\n *\n * @param {number} [scale] 小数桁数 デフォルトは0\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {Decimal}\n */\n public round(scale: number = 0, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): Decimal {\n return Decimal.wrap(this.big.round(scale, roundingMode));\n }\n\n /**\n * 絶対値を返す\n *\n * @returns {Decimal}\n */\n public abs(): Decimal {\n return Decimal.wrap(this.big.abs());\n }\n\n /**\n * 値を比較する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {-1 | 0 | 1} 自身が小さければ-1、等しければ0、大きければ1\n */\n public compareTo(value: DecimalSource): -1 | 0 | 1 {\n return this.big.cmp(Decimal.toBig(value));\n }\n\n /**\n * 等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public eq(value: DecimalSource): boolean {\n return this.compareTo(value) === 0;\n }\n\n /**\n * 自身が小さいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lt(value: DecimalSource): boolean {\n return this.compareTo(value) < 0;\n }\n\n /**\n * 自身が小さいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lte(value: DecimalSource): boolean {\n return this.compareTo(value) <= 0;\n }\n\n /**\n * 自身が大きいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gt(value: DecimalSource): boolean {\n return 0 < this.compareTo(value);\n }\n\n /**\n * 自身が大きいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gte(value: DecimalSource): boolean {\n return 0 <= this.compareTo(value);\n }\n\n /**\n * numberに変換する\n * Number.MAX_SAFE_INTEGERを超える値や、numberで表現できない桁数の小数は精度が落ちる\n *\n * @returns {number}\n */\n public toNumber(): number {\n return this.big.toNumber();\n }\n\n /**\n * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n * 丸めた結果が0になる場合は符号を付けない\n *\n * @param {number} scale 小数桁数\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n */\n public toFixed(scale: number, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): string {\n return this.big.round(scale, roundingMode).toFixed(scale);\n }\n\n /**\n * 文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n *\n * @returns {string}\n */\n public toString(): string {\n return this.big.toFixed();\n }\n}\n"],"names":["ROUNDING_MODE","DIVISION_SCALE","NUMERIC_STRING_PATTERN","BigNumber","Big","isEmpty","value","Decimal","trimmed","big","decimal","divisor","scale","roundingMode"],"mappings":"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"}
1
+ {"version":3,"file":"decimal.js","sources":["../src/decimal.ts"],"sourcesContent":["/**\n * このクラス Decimal の役割は、算術演算の実体としての Big を内部に閉じ込め、利用者側に露出させないことにある。\n * 2026-10-08時点では big.js に依存しているが、将来的に演算演算のライブラリを変更した場合に\n * 安全・簡単に移行できることを目的としている。\n */\nimport { Big } from 'big.js';\n\n/**\n * 数値として扱える値の型\n */\nexport type NumberSource = number | string | bigint | Decimal;\n\n/**\n * 丸めモード\n */\nexport const ROUNDING_MODE = {\n /**\n * Rounds towards zero.\n * I.e. truncate, no rounding.\n */\n roundDown: 0,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds away from zero.\n */\n roundHalfUp: 1,\n /**\n * Rounds towards nearest neighbour.\n * If equidistant, rounds towards even neighbour.\n */\n roundHalfEven: 2,\n /**\n * Rounds away from zero.\n */\n roundUp: 3\n} as const;\n\nexport type RoundingMode = typeof ROUNDING_MODE[keyof typeof ROUNDING_MODE];\n\n/**\n * Decimalの生成・演算に渡せる値の型\n * null/undefined/空文字/NaNは0とみなす(divの割る値は1とみなす)\n */\nexport type DecimalSource = NumberSource | null | undefined;\n\n/** 除算で保持する小数桁数 */\nconst DIVISION_SCALE = 20;\n\n/** 数値として解釈できる文字列のパターン(符号・小数点・指数表記) */\nconst NUMERIC_STRING_PATTERN = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n// 独立したコンストラクタにすることで、利用側がグローバルの Big.DP / Big.RM を書き換えても影響を受けないようにする\nconst BigNumber = Big();\nBigNumber.DP = DIVISION_SCALE;\nBigNumber.RM = ROUNDING_MODE.roundHalfUp;\n\n// null/undefined/空文字/NaNはtrueを返す\nconst isEmpty = (value: DecimalSource): value is null | undefined | '' => value == null || value === '' || (typeof value === 'number' && Number.isNaN(value));\n\n/**\n * 任意精度の10進数を表す不変オブジェクト\n * 演算メソッドは自身を変更せず、結果を新しいインスタンスで返す\n * 除算は小数20桁(roundHalfUp)まで保持し、それ以降の桁は切り捨てではなく丸める\n */\nexport class Decimal {\n /** 丸めモード */\n public static readonly ROUNDING_MODE = ROUNDING_MODE;\n\n /**\n * 算術演算インスタンス\n */\n private big: Big;\n\n /**\n * @param {DecimalSource} value 数値、数値文字列、bigint、Decimal\n * null/undefined/空文字/NaNは0とみなす\n * 数値として解釈できない文字列・Infinityは TypeError をスローする\n */\n constructor(value: DecimalSource) {\n this.big = Decimal.toBig(value);\n }\n\n private static toBig(value: DecimalSource): Big {\n if (isEmpty(value)) {\n return BigNumber(0);\n }\n if (value instanceof Decimal) {\n return value.big;\n }\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n return BigNumber(value);\n case 'bigint':\n return BigNumber(value.toString());\n default: {\n const trimmed = value.trim();\n if (!NUMERIC_STRING_PATTERN.test(trimmed)) {\n throw new TypeError(`Invalid number: ${value}`);\n }\n // 先頭の '+' は数値として解釈できる表記だが、内部の算術ライブラリが受け付けないため取り除く\n return BigNumber(trimmed.replace(/^\\+/, ''));\n }\n }\n }\n\n private static wrap(big: Big): Decimal {\n const decimal = new Decimal(0);\n decimal.big = big;\n return decimal;\n }\n\n /**\n * 加算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public add(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.add(Decimal.toBig(value)));\n }\n\n /**\n * 減算した結果を返す\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public sub(value: DecimalSource): Decimal {\n return Decimal.wrap(this.big.sub(Decimal.toBig(value)));\n }\n\n /**\n * 乗算した結果を返す\n * null/undefined/空文字/NaNは0とみなすため、結果は0になる\n * 元の値を保持したい場合は times(discount ?? 1) のようにフォールバック値を指定する\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public times(value: DecimalSource): Decimal {\n // 掛ける値が空のとき、0とみなすべきか元の値を保持すべきかは計算対象によって異なる\n // 手数料 x 件数: 件数が未定義なら総額は0が適切\n // 商品価格 x 割引率: 割引率が未定義なら元の価格が適切\n // 1とみなすと、new Decimal(null).times(3) は 0、new Decimal(3).times(null) は 3 になり、引数の順序で結果が変わる\n // そのため常に0とみなし、元の値を保持したい場合は呼び出し側でフォールバック値を指定する\n return Decimal.wrap(this.big.times(Decimal.toBig(value)));\n }\n\n /**\n * 除算した結果を返す\n * 結果は小数20桁(roundHalfUp)まで保持する\n * 割る値のnull/undefined/空文字/NaNは1とみなすため、結果は元の値と同じになる\n * 割る値に0を指定した場合は RangeError をスローする\n *\n * @param {DecimalSource} value\n * @returns {Decimal}\n */\n public div(value: DecimalSource): Decimal {\n // 割る値が空のとき、0とみなすとすべてゼロ除算エラーになり計算が成り立たないため1とみなす\n if (isEmpty(value)) {\n return Decimal.wrap(this.big);\n }\n const divisor = Decimal.toBig(value);\n if (divisor.eq(0)) {\n throw new RangeError('Division by zero');\n }\n return Decimal.wrap(this.big.div(divisor));\n }\n\n /**\n * 指定した小数桁で丸めた結果を返す\n * 負の桁数を指定すると整数部を丸める(-2 なら百の位)\n *\n * @param {number} [scale] 小数桁数 デフォルトは0\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {Decimal}\n */\n public round(scale: number = 0, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): Decimal {\n return Decimal.wrap(this.big.round(scale, roundingMode));\n }\n\n /**\n * 絶対値を返す\n *\n * @returns {Decimal}\n */\n public abs(): Decimal {\n return Decimal.wrap(this.big.abs());\n }\n\n /**\n * 値を比較する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {-1 | 0 | 1} 自身が小さければ-1、等しければ0、大きければ1\n */\n public compareTo(value: DecimalSource): -1 | 0 | 1 {\n return this.big.cmp(Decimal.toBig(value));\n }\n\n /**\n * 等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public eq(value: DecimalSource): boolean {\n return this.compareTo(value) === 0;\n }\n\n /**\n * 自身が小さいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lt(value: DecimalSource): boolean {\n return this.compareTo(value) < 0;\n }\n\n /**\n * 自身が小さいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public lte(value: DecimalSource): boolean {\n return this.compareTo(value) <= 0;\n }\n\n /**\n * 自身が大きいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gt(value: DecimalSource): boolean {\n return 0 < this.compareTo(value);\n }\n\n /**\n * 自身が大きいか等しいか判定する\n * null/undefined/空文字/NaNは0とみなす\n *\n * @param {DecimalSource} value\n * @returns {boolean}\n */\n public gte(value: DecimalSource): boolean {\n return 0 <= this.compareTo(value);\n }\n\n /**\n * numberに変換する\n * Number.MAX_SAFE_INTEGERを超える値や、numberで表現できない桁数の小数は精度が落ちる\n *\n * @returns {number}\n */\n public toNumber(): number {\n return this.big.toNumber();\n }\n\n /**\n * 指定した小数桁で丸め、小数桁を0で埋めた文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n * ゼロでない値を丸めて0になる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')\n *\n * @param {number} scale 小数桁数\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n */\n public toFixed(scale: number, roundingMode: RoundingMode = ROUNDING_MODE.roundHalfUp): string {\n return this.big.toFixed(scale, roundingMode);\n }\n\n /**\n * 文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n *\n * @returns {string}\n */\n public toString(): string {\n return this.big.toFixed();\n }\n}\n"],"names":["ROUNDING_MODE","DIVISION_SCALE","NUMERIC_STRING_PATTERN","BigNumber","Big","isEmpty","value","Decimal","trimmed","big","decimal","divisor","scale","roundingMode"],"mappings":"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"}
package/lib/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./crypto-util-BcHurtbE.cjs"),e=require("./zoned-date-time.cjs"),i=require("./date-util-CZmiQEYH.cjs"),l=require("./decimal.cjs"),r=require("./file-util-8dZPFn1f.cjs"),o=require("./html-util-DAqLW2ol.cjs"),U=require("./json-util-CKnsxu1e.cjs"),n=require("./number-util-DCmpmp10.cjs"),c=require("./object-util-Bt_GY7ls.cjs"),s=require("./string-util-w2I5EYuY.cjs");exports.CryptoUtil=t.cryptoUtil;exports.ZonedDateTime=e.ZonedDateTime;exports.DateUtil=i.dateUtil;exports.Decimal=l.Decimal;exports.FileUtil=r.fileUtil;exports.HtmlUtil=o.htmlUtil;exports.JsonUtil=U.jsonUtil;exports.NumberUtil=n.numberUtil;exports.ObjectUtil=c.objectUtil;exports.StringUtil=s.stringUtil;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./crypto-util-BcHurtbE.cjs"),e=require("./zoned-date-time.cjs"),i=require("./date-util-CZmiQEYH.cjs"),l=require("./decimal.cjs"),r=require("./file-util-8dZPFn1f.cjs"),o=require("./html-util-DAqLW2ol.cjs"),U=require("./json-util-CKnsxu1e.cjs"),n=require("./number-util-Id88azzp.cjs"),c=require("./object-util-B2Y5kgmz.cjs"),s=require("./string-util-w2I5EYuY.cjs");exports.CryptoUtil=t.cryptoUtil;exports.ZonedDateTime=e.ZonedDateTime;exports.DateUtil=i.dateUtil;exports.Decimal=l.Decimal;exports.FileUtil=r.fileUtil;exports.HtmlUtil=o.htmlUtil;exports.JsonUtil=U.jsonUtil;exports.NumberUtil=n.numberUtil;exports.ObjectUtil=c.objectUtil;exports.StringUtil=s.stringUtil;
2
2
  //# sourceMappingURL=index.cjs.map
package/lib/index.js CHANGED
@@ -5,8 +5,8 @@ import { Decimal as l } from "./decimal.js";
5
5
  import { f as s } from "./file-util-DrU0xUXt.js";
6
6
  import { h as U } from "./html-util-EI6f5f8f.js";
7
7
  import { j as c } from "./json-util-C_Pm1BpJ.js";
8
- import { n as b } from "./number-util-D7xL_wKq.js";
9
- import { o as j } from "./object-util-BzHiXpIS.js";
8
+ import { n as b } from "./number-util-VglV39jg.js";
9
+ import { o as j } from "./object-util-BdG4k5RD.js";
10
10
  import { s as h } from "./string-util-Cw0VgbIH.js";
11
11
  export {
12
12
  r as CryptoUtil,
@@ -0,0 +1,2 @@
1
+ "use strict";const i=require("./decimal.cjs"),C=new i.Decimal("-9223372036854775808"),V=new i.Decimal("9223372036854775807"),D=new RegExp("([+-]?)([0-9]*)[.]?([0-9]*)"),F=/^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i,d=e=>typeof e=="string"&&e.trim()==="";function w(e,r){if(e==null||d(e))return!1;const t=Number.isFinite(r?.minValue)?new i.Decimal(r.minValue):C;try{return t.lte(e)&&V.gte(e)}catch{return!1}}function g(e,r,t){if(e==null||e==="")return"";let n;switch(typeof e){case"number":if(!Number.isFinite(e))return String(e);n=new i.Decimal(e).toString();break;case"string":if(n=a(e).trim(),!F.test(n))return e;/e/i.test(n)&&(n=`${n.startsWith("+")?"+":""}${new i.Decimal(n).toString()}`);break;default:n=e.toString()}const o=D.exec(n),l=o[1];let u=o[2]||"0",c=o[3],f,s=new i.Decimal(`${l==="-"?"-":""}${u}.${c}`);const y=s.eq(0);if(r!=null){s=s.round(r,t??i.ROUNDING_MODE.roundHalfUp);const N=D.exec(s.toString());u=N[2],c=N[3],f=r}else f=c.length;const b=y?"":l;return u=u.replace(/(\d)(?=(\d{3})+$)/g,"$1,"),c=`${c}${"0".repeat(f)}`.substring(0,f),c===""?`${b}${u}`:`${b}${u}.${c}`}function a(e){return e.replace(/,/g,"")}function $(e,r){return new Intl.NumberFormat(r,{notation:"compact"}).format(Object.is(e,-0)?0:e)}function p(e,r,t){let n=new i.Decimal(e);for(const o of r)n=n[o.operator](o.value);return t?.scale!=null&&(n=n.round(t.scale,t.roundingMode??i.ROUNDING_MODE.roundHalfUp)),n.toNumber()}function O(e,...r){let t=new i.Decimal(e);for(const n of r)t=t.add(n);return t.toNumber()}function S(e,...r){let t=new i.Decimal(e);for(const n of r)t=t.sub(n);return t.toNumber()}function M(e,...r){let t=new i.Decimal(e);for(const n of r)t=t.times(n);return t.toNumber()}function h(e,...r){let t=new i.Decimal(e);for(const n of r)t=t.div(n);return t.toNumber()}function m(e,r){return new i.Decimal(e).compareTo(r)}function U(e,r){return m(e,r)===0}function _(e,r){return m(e,r)<0}function R(e,r){return m(e,r)<=0}function E(e,r){return 0<m(e,r)}function G(e,r){return 0<=m(e,r)}function I(e,r,t){if(e==null)return null;const n=t??i.ROUNDING_MODE.roundHalfUp;switch(typeof e){case"number":return Number.isFinite(e)?new i.Decimal(e).round(r,n).toNumber():e;case"string":{if(d(e))return null;try{return new i.Decimal(e).round(r,n).toNumber()}catch{return Number.NaN}}default:return new i.Decimal(e).round(r,n).toNumber()}}function T(e,r){if(e==null)return"";if(d(e)||typeof e=="number"&&!Number.isFinite(e))return String(e);try{const t=new i.Decimal(e);return r?.scale!=null?t.toFixed(r.scale,r.roundingMode??i.ROUNDING_MODE.roundHalfUp):t.toString()}catch{return String(e)}}function B(e,r){if(e==null||d(e))switch(r?.empty){case"undefined":return;case"zero":return 0;default:return null}let t;switch(typeof e){case"number":t=e;break;case"bigint":t=Number(e);break;case"string":t=Number(a(e).trim());break;default:t=e.toNumber()}if(Number.isNaN(t))switch(r?.nan){case"null":return null;case"undefined":return;default:return t}return t}function k(e,r){if(e==null||e==="")return[String(e),""];let t;switch(typeof e){case"number":if(Number.isNaN(e))return["NaN",""];t=new i.Decimal(e);break;case"string":try{t=new i.Decimal(a(e))}catch{return[e,""]}break;default:t=new i.Decimal(e)}const n=["B","KB","MB","GB","TB"];let o=0;for(;t.gte(1024)&&o<n.length-1;)t=t.div(1024),o++;const l=r?.scale??2,u=r?.roundingMode??i.ROUNDING_MODE.roundHalfUp;return r?.format?[g(t.toString(),l,u),n[o]]:[t.round(l,u).toString(),n[o]]}const H=Object.freeze(Object.defineProperty({__proto__:null,ROUNDING_MODE:i.ROUNDING_MODE,add:O,calc:p,compareTo:m,div:h,eq:U,formatBytes:k,formatComma:g,formatCompact:$,gt:E,gte:G,isLongValue:w,lt:_,lte:R,removeComma:a,round:I,sub:S,times:M,toNumber:B,toString:T},Symbol.toStringTag,{value:"Module"}));exports.add=O;exports.calc=p;exports.compareTo=m;exports.div=h;exports.eq=U;exports.formatBytes=k;exports.formatComma=g;exports.formatCompact=$;exports.gt=E;exports.gte=G;exports.isLongValue=w;exports.lt=_;exports.lte=R;exports.numberUtil=H;exports.removeComma=a;exports.round=I;exports.sub=S;exports.times=M;exports.toNumber=B;exports.toString=T;
2
+ //# sourceMappingURL=number-util-Id88azzp.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-util-Id88azzp.cjs","sources":["../src/number-util.ts"],"sourcesContent":["import { Decimal, ROUNDING_MODE } from './decimal';\nimport type { NumberSource, RoundingMode } from './decimal';\n\nexport { ROUNDING_MODE };\nexport type { NumberSource, RoundingMode };\n\n// 64bit整数の範囲\nconst MIN_LONG = new Decimal('-9223372036854775808');\nconst MAX_LONG = new Decimal('9223372036854775807');\n\n/** 数値パターン */\nconst NUMBER_PATTERN = new RegExp('([\\+\\-]?)([0-9]*)[\\.]?([0-9]*)');\n\n/** 数値として解釈できる文字列のパターン(符号・小数点・指数表記) */\nconst NUMERIC_STRING_PATTERN = /^[+-]?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\n// 空文字・空白のみの文字列はtrueを返す\nconst isBlank = (value: unknown): value is string => typeof value === 'string' && value.trim() === '';\n\n/**\n * long(64bit)の範囲(-9223372036854775808〜9223372036854775807)の値か判定する\n * Javascriptのnumberの範囲は(-9007199254740991〜9007199254740991)である\n *\n * @param {string | bigint | Decimal} value\n * @param {*} [options]\n * ├ minValue number 最小値を指定する場合(0を指定すると負数の場合falseを返す)\n * 不正な値を指定した場合は無視される(最小値を-9223372036854775808とみなす)\n * @returns {boolean}\n * @see Number.MAX_SAFE_INTEGER\n * @see Number.MIN_SAFE_INTEGER\n */\nexport function isLongValue(value: string | bigint | Decimal, options?: {\n minValue?: number;\n}): boolean {\n if (value == null || isBlank(value)) {\n return false;\n }\n const min = Number.isFinite(options?.minValue) ? new Decimal(options!.minValue) : MIN_LONG;\n try {\n // -9223372036854775808 <= value <= 9223372036854775807\n return min.lte(value) && MAX_LONG.gte(value);\n } catch (error) {\n // 数値として解釈できない値\n return false;\n }\n}\n\n/**\n * 3桁ごとカンマ区切りした文字列を返す\n * 指数表記の値(1e21など)は通常の表記に展開してから区切る\n * 数値として解釈できない文字列はそのまま返し、NaN/Infinityは \"NaN\"/\"Infinity\"/\"-Infinity\" を返す\n *\n * @param {NumberSource | null | undefined} value 値\n * @param {number} [scale] 小数点桁数(補助桁数)\n * @param {RoundingMode} [roundingMode] 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n */\nexport function formatComma(value: NumberSource | null | undefined, scale?: number, roundingMode?: RoundingMode): string {\n if (value == null || value === '') {\n // 空文字を返却\n return '';\n }\n let strValue: string;\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n // \"NaN\" / \"Infinity\" / \"-Infinity\" を返却\n return String(value);\n }\n // toString()は1e21以上や1e-7以下を指数表記にするため、Decimalで通常の表記に展開する\n strValue = new Decimal(value).toString();\n break;\n case 'string':\n strValue = removeComma(value).trim();\n if (!NUMERIC_STRING_PATTERN.test(strValue)) {\n // 元の文字列を返却\n return value;\n }\n if (/e/i.test(strValue)) {\n // 指数表記を通常の表記に展開する。表示用に '+' を付け直す\n const plusSign = strValue.startsWith('+') ? '+' : '';\n strValue = `${plusSign}${new Decimal(strValue).toString()}`;\n }\n break;\n default:\n // bigint・Decimalの場合\n strValue = value.toString();\n }\n const matches = NUMBER_PATTERN.exec(strValue) as RegExpExecArray;\n const sign = matches[1];\n let natural = matches[2] || '0';\n let decimal = matches[3];\n let dp: number;\n let decimalValue = new Decimal(`${sign === '-' ? '-' : ''}${natural}.${decimal}`);\n const isZero = decimalValue.eq(0);\n if (scale != null) {\n decimalValue = decimalValue.round(scale, roundingMode ?? ROUNDING_MODE.roundHalfUp);\n const roundedMatches = NUMBER_PATTERN.exec(decimalValue.toString()) as RegExpExecArray;\n natural = roundedMatches[2];\n decimal = roundedMatches[3];\n dp = scale;\n } else {\n dp = decimal.length;\n }\n // 値がゼロのときは符号を付けない。ゼロでない値を丸めてゼロになる場合は、JSのtoFixedと同じく符号を残す('-0.001' を小数2桁にすると '-0.00')\n const displaySign = isZero ? '' : sign;\n natural = natural.replace(/(\\d)(?=(\\d{3})+$)/g, '$1,');\n decimal = `${decimal}${'0'.repeat(dp)}`.substring(0, dp);\n return decimal === ''\n ? `${displaySign}${natural}`\n : `${displaySign}${natural}.${decimal}`;\n}\n\n/**\n * カンマを除去する\n *\n * @param {string} value 入力値\n * @returns {string} カンマを取り除いた文字列\n */\nexport function removeComma(value: string): string {\n return value.replace(/,/g, '');\n}\n\n/**\n * 数値を表示ロケールの短縮表記にする。\n * en は 1.2K/3.4M/5.6B、ja は 12万/34億 のように単位が切り替わる。\n *\n * @param {number} value 値\n * @param {string} locale 表示ロケール(例 'ja' / 'en')\n * @returns {string} 短縮表記の文字列\n */\nexport function formatCompact(value: number, locale: string): string {\n // Intl.NumberFormat は -0 を '-0' と表示するため、String(-0) と同じく符号なしの 0 にそろえる\n return new Intl.NumberFormat(locale, { notation: 'compact' }).format(Object.is(value, -0) ? 0 : value);\n}\n\nexport type Operator = 'add' | 'sub' | 'times' | 'div';\n\nexport interface OperationItem {\n operator: Operator;\n value: NumberSource | null | undefined;\n}\n\n/**\n * 複数の演算をまとめて計算する\n * 計算途中は精度を保持し、最後にnumberへ変換する\n * この関数では四則演算の優先順位はなく、与えられた配列の順で計算を行う\n * * 優先順位やカッコの概念がある場合は事前に計算したうえでこの関数を利用する\n *\n * 例)\n * calc(\n * '123',\n * [\n * { operator: 'add', value: '123' },\n * { operator: 'sub', value: 100 },\n * { operator: 'times', value: 2 },\n * { operator: 'div', value: 3 }\n * ]\n * )\n * 123 + 123 = 246\n * 246 - 100 = 146\n * 146 * 2 = 292\n * 292 / 3 = 97.33333333\n *\n * null等の扱いは add / sub / times / div と同じ\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} initialValue\n * @param {OperationItem[]} operationItems\n * ├ operator: Operator\n * ├ value: NumberSource | null | undefined\n * @param {*} [options]\n * ├ scale 計算結果を丸める小数桁数。指定しない場合は丸めない\n * ├ roundingMode 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {number}\n */\nexport function calc(initialValue: NumberSource | null | undefined, operationItems: OperationItem[], options?: {\n scale?: number;\n roundingMode?: RoundingMode;\n}): number {\n let decimal = new Decimal(initialValue);\n for (const item of operationItems) {\n decimal = decimal[item.operator](item.value);\n }\n if (options?.scale != null) {\n decimal = decimal.round(options.scale, options.roundingMode ?? ROUNDING_MODE.roundHalfUp);\n }\n return decimal.toNumber();\n}\n\n/**\n * 加算を行う\n * null/undefined/空文字/NaNは0と見做されるため、演算結果に影響しない\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {(NumberSource | null | undefined)[]} value2\n * @returns {number}\n */\nexport function add(value1: NumberSource | null | undefined, ...value2: (NumberSource | null | undefined)[]): number {\n let decimal = new Decimal(value1);\n for (const value of value2) {\n decimal = decimal.add(value);\n }\n return decimal.toNumber();\n}\n\n/**\n * 減算を行う\n * null/undefined/空文字/NaNは0と見做されるため、演算結果に影響しない\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {(NumberSource | null | undefined)[]} value2\n * @returns {number}\n */\nexport function sub(value1: NumberSource | null | undefined, ...value2: (NumberSource | null | undefined)[]): number {\n let decimal = new Decimal(value1);\n for (const value of value2) {\n decimal = decimal.sub(value);\n }\n return decimal.toNumber();\n}\n\n/**\n * 乗算を行う\n * null/undefined/空文字/NaNは0と見做されるため、演算結果は0になる\n * 元の値を保持したい場合は times(price, discount ?? 1) のようにフォールバック値を指定する\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {(NumberSource | null | undefined)[]} value2\n * @returns {number}\n */\nexport function times(value1: NumberSource | null | undefined, ...value2: (NumberSource | null | undefined)[]): number {\n let decimal = new Decimal(value1);\n for (const value of value2) {\n decimal = decimal.times(value);\n }\n return decimal.toNumber();\n}\n\n/**\n * 除算を行う\n * 割る値のnull/undefined/空文字/NaNは1と見做されるため、演算結果に影響しない\n * 割る値に0を指定した場合はゼロ除算エラーになる\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {(NumberSource | null | undefined)[]} value2\n * @returns {number}\n */\nexport function div(value1: NumberSource | null | undefined, ...value2: (NumberSource | null | undefined)[]): number {\n let decimal = new Decimal(value1);\n for (const value of value2) {\n decimal = decimal.div(value);\n }\n return decimal.toNumber();\n}\n\n/**\n * 2つの値を数値として比較する\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {-1 | 0 | 1} value1がvalue2より小さい場合は-1、等しい場合は0、大きい場合は1\n */\nexport function compareTo(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): -1 | 0 | 1 {\n return new Decimal(value1).compareTo(value2);\n}\n\n/**\n * 2つの値が数値として等しいかを返す\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {boolean}\n */\nexport function eq(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): boolean {\n return compareTo(value1, value2) === 0;\n}\n\n/**\n * value1がvalue2より小さいかを返す\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {boolean}\n */\nexport function lt(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): boolean {\n return compareTo(value1, value2) < 0;\n}\n\n/**\n * value1がvalue2以下かを返す\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {boolean}\n */\nexport function lte(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): boolean {\n return compareTo(value1, value2) <= 0;\n}\n\n/**\n * value1がvalue2より大きいかを返す\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {boolean}\n */\nexport function gt(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): boolean {\n return 0 < compareTo(value1, value2);\n}\n\n/**\n * value1がvalue2以上かを返す\n * null/undefined/空文字/NaNは0と見做す\n * 数値として解釈できない文字列やInfinityを指定した場合はTypeErrorになる\n *\n * @param {NumberSource | null | undefined} value1\n * @param {NumberSource | null | undefined} value2\n * @returns {boolean}\n */\nexport function gte(value1: NumberSource | null | undefined, value2: NumberSource | null | undefined): boolean {\n return 0 <= compareTo(value1, value2);\n}\n\n/**\n * 数値を指定した桁で丸める\n * null/undefined/空文字はnull、数値として解釈できない文字列はNaNを返す\n * NaN/Infinityはそのまま返す\n * 戻り値はnumberのため、Number.MAX_SAFE_INTEGERを超える結果は精度が落ちる\n *\n * @param {NumberSource | null | undefined} value\n * @param {number} scale\n * @param {RoundingMode} [roundingMode] デフォルトは 1: 四捨五入\n * 0 切り捨て\n * 1 四捨五入\n * 2 ISO丸め\n * 3 切り上げ\n * @returns {number | null}\n * @see ROUNDING_MODE\n */\nexport function round(\n value: NumberSource | null | undefined,\n scale: number,\n roundingMode?: RoundingMode\n): number | null {\n if (value == null) {\n return null;\n }\n const rm = roundingMode ?? ROUNDING_MODE.roundHalfUp;\n switch (typeof value) {\n case 'number':\n if (!Number.isFinite(value)) {\n // NaN/Infinityはそのまま返す\n return value;\n }\n return new Decimal(value).round(scale, rm).toNumber();\n case 'string': {\n if (isBlank(value)) {\n // 空文字は値なしとしてnullと同じ扱いにする\n return null;\n }\n try {\n return new Decimal(value).round(scale, rm).toNumber();\n } catch (error) {\n // 数値として解釈できない文字列\n return Number.NaN;\n }\n }\n default:\n return new Decimal(value).round(scale, rm).toNumber();\n }\n}\n\n/**\n * 数値文字列に変換する\n * 指数表記にはならず、通常の表記で返す\n * 数値として解釈できない値はString(value)を返す\n *\n * @param {NumberSource | null | undefined} value\n * @param {*} [options]\n * ├ scale 小数桁数。指定しない場合は丸めずにすべての桁を返す\n * ├ roundingMode 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * @returns {string}\n * @see ROUNDING_MODE\n */\nexport function toString(\n value: NumberSource | null | undefined,\n options?: {\n scale?: number;\n roundingMode?: RoundingMode;\n }\n): string {\n if (value == null) {\n return '';\n }\n if (isBlank(value) || (typeof value === 'number' && !Number.isFinite(value))) {\n // 空文字・NaN・Infinityは数値として扱わない\n return String(value);\n }\n try {\n const decimal = new Decimal(value);\n return options?.scale != null\n ? decimal.toFixed(options.scale, options.roundingMode ?? ROUNDING_MODE.roundHalfUp)\n : decimal.toString();\n } catch (error) {\n return String(value);\n }\n}\n\n/** toNumber のオプション */\nexport interface ToNumberOptions {\n /** 未指定(null・undefined・空白のみの文字列)のときに返す値。デフォルトは 'null' */\n empty?: 'null' | 'undefined' | 'zero';\n /** 数値として解釈できない(結果が NaN になる)ときに返す値。デフォルトは 'NaN' */\n nan?: 'NaN' | 'null' | 'undefined';\n}\n\n/** options.empty に応じた未指定時の戻り値の型。'zero' は number に含まれるので never */\ntype EmptyResult<O extends ToNumberOptions> = O extends { empty?: infer E }\n ? E extends 'undefined' ? undefined : E extends 'zero' ? never : null\n : null;\n\n/** options.nan に応じた変換不可時の戻り値の型。'NaN' は number に含まれるので never */\ntype NanResult<O extends ToNumberOptions> = O extends { nan?: infer N }\n ? N extends 'null' ? null : N extends 'undefined' ? undefined : never\n : never;\n\n/**\n * 数値に変換する\n * 文字列はカンマと前後の空白を除いてから変換する\n * null・undefined・空白のみの文字列は未指定として扱い、options.empty に応じて null(デフォルト)・undefined・0 のいずれかを返す\n * 数値として解釈できない場合は options.nan に応じて NaN(デフォルト)・null・undefined のいずれかを返す\n *\n * @param {NumberSource | null | undefined} value\n * @param {ToNumberOptions} [options]\n * ├ empty 未指定のときに返す値。'null'(デフォルト) | 'undefined' | 'zero'\n * └ nan 数値として解釈できないときに返す値。'NaN'(デフォルト) | 'null' | 'undefined'\n * @returns {number | EmptyResult<O> | NanResult<O>} 戻り値の型は options に連動する\n */\nexport function toNumber<O extends ToNumberOptions = Record<never, never>>(value: NumberSource | null | undefined, options?: O): number | EmptyResult<O> | NanResult<O> {\n type Result = number | EmptyResult<O> | NanResult<O>;\n if (value == null || isBlank(value)) {\n switch (options?.empty) {\n case 'undefined':\n return undefined as Result;\n case 'zero':\n return 0;\n default:\n return null as Result;\n }\n }\n let result: number;\n switch (typeof value) {\n case 'number':\n result = value;\n break;\n case 'bigint':\n result = Number(value);\n break;\n case 'string':\n result = Number(removeComma(value).trim());\n break;\n default:\n // Decimalの場合\n result = value.toNumber();\n }\n if (Number.isNaN(result)) {\n switch (options?.nan) {\n case 'null':\n return null as Result;\n case 'undefined':\n return undefined as Result;\n default:\n return result;\n }\n }\n return result;\n}\n\n/**\n * 渡されたバイト数値を桁数に応じてMB,GBなどに単位を変更する\n *\n * @param {NumberSource} bytes\n * @param {*} [options]\n * ┝ scale 小数以下桁数 デフォルト:2\n * ┝ roundingMode 丸めモード デフォルトはROUNDING_MODE.roundHalfUp(四捨五入・half-away-from-zero)\n * ┝ format フォーマットするか。trueを指定した場合、3桁カンマ区切り+小数末尾0の桁揃え\n * @returns {[string, string]} 精度以下を丸めた数値(文字列)と単位をタプルで返す\n */\nexport function formatBytes(\n bytes: NumberSource,\n options?: {\n scale?: number;\n roundingMode?: RoundingMode;\n format?: boolean;\n }\n): [string, string] {\n if (bytes == null || bytes === '') {\n return [String(bytes), ''];\n }\n let decimalValue: Decimal;\n switch (typeof bytes) {\n case 'number':\n if (Number.isNaN(bytes)) {\n // \"NaN\" を返却\n return ['NaN', ''];\n }\n decimalValue = new Decimal(bytes);\n break;\n case 'string':\n try {\n decimalValue = new Decimal(removeComma(bytes));\n } catch (error) {\n // 元の文字列を返却\n return [bytes, ''];\n }\n break;\n default:\n // bigint・Decimalの場合\n decimalValue = new Decimal(bytes);\n }\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n let i = 0;\n while (decimalValue.gte(1024) && i < units.length - 1) {\n decimalValue = decimalValue.div(1024);\n i++;\n }\n const scale = options?.scale ?? 2;\n const roundingMode = options?.roundingMode ?? ROUNDING_MODE.roundHalfUp;\n if (options?.format) {\n return [formatComma(decimalValue.toString(), scale, roundingMode), units[i]];\n }\n return [decimalValue.round(scale, roundingMode).toString(), units[i]];\n}\n"],"names":["MIN_LONG","Decimal","MAX_LONG","NUMBER_PATTERN","NUMERIC_STRING_PATTERN","isBlank","value","isLongValue","options","min","formatComma","scale","roundingMode","strValue","removeComma","matches","sign","natural","decimal","dp","decimalValue","isZero","ROUNDING_MODE","roundedMatches","displaySign","formatCompact","locale","calc","initialValue","operationItems","item","add","value1","value2","sub","times","div","compareTo","eq","lt","lte","gt","gte","round","rm","toString","toNumber","result","formatBytes","bytes","units","i"],"mappings":"8CAOMA,EAAW,IAAIC,EAAAA,QAAQ,sBAAsB,EAC7CC,EAAW,IAAID,EAAAA,QAAQ,qBAAqB,EAG5CE,EAAiB,IAAI,OAAO,6BAAgC,EAG5DC,EAAyB,wCAGzBC,EAAWC,GAAoC,OAAOA,GAAU,UAAYA,EAAM,SAAW,GAc5F,SAASC,EAAYD,EAAkCE,EAElD,CACV,GAAIF,GAAS,MAAQD,EAAQC,CAAK,EAChC,MAAO,GAET,MAAMG,EAAM,OAAO,SAASD,GAAS,QAAQ,EAAI,IAAIP,UAAQO,EAAS,QAAQ,EAAIR,EAClF,GAAI,CAEF,OAAOS,EAAI,IAAIH,CAAK,GAAKJ,EAAS,IAAII,CAAK,CAC7C,MAAgB,CAEd,MAAO,EACT,CACF,CAYO,SAASI,EAAYJ,EAAwCK,EAAgBC,EAAqC,CACvH,GAAIN,GAAS,MAAQA,IAAU,GAE7B,MAAO,GAET,IAAIO,EACJ,OAAQ,OAAOP,EAAA,CACb,IAAK,SACH,GAAI,CAAC,OAAO,SAASA,CAAK,EAExB,OAAO,OAAOA,CAAK,EAGrBO,EAAW,IAAIZ,EAAAA,QAAQK,CAAK,EAAE,SAAA,EAC9B,MACF,IAAK,SAEH,GADAO,EAAWC,EAAYR,CAAK,EAAE,KAAA,EAC1B,CAACF,EAAuB,KAAKS,CAAQ,EAEvC,OAAOP,EAEL,KAAK,KAAKO,CAAQ,IAGpBA,EAAW,GADMA,EAAS,WAAW,GAAG,EAAI,IAAM,EAC5B,GAAG,IAAIZ,EAAAA,QAAQY,CAAQ,EAAE,UAAU,IAE3D,MACF,QAEEA,EAAWP,EAAM,SAAA,CAAS,CAE9B,MAAMS,EAAUZ,EAAe,KAAKU,CAAQ,EACtCG,EAAOD,EAAQ,CAAC,EACtB,IAAIE,EAAUF,EAAQ,CAAC,GAAK,IACxBG,EAAUH,EAAQ,CAAC,EACnBI,EACAC,EAAe,IAAInB,EAAAA,QAAQ,GAAGe,IAAS,IAAM,IAAM,EAAE,GAAGC,CAAO,IAAIC,CAAO,EAAE,EAChF,MAAMG,EAASD,EAAa,GAAG,CAAC,EAChC,GAAIT,GAAS,KAAM,CACjBS,EAAeA,EAAa,MAAMT,EAAOC,GAAgBU,EAAAA,cAAc,WAAW,EAClF,MAAMC,EAAiBpB,EAAe,KAAKiB,EAAa,UAAU,EAClEH,EAAUM,EAAe,CAAC,EAC1BL,EAAUK,EAAe,CAAC,EAC1BJ,EAAKR,CACP,MACEQ,EAAKD,EAAQ,OAGf,MAAMM,EAAcH,EAAS,GAAKL,EAClC,OAAAC,EAAUA,EAAQ,QAAQ,qBAAsB,KAAK,EACrDC,EAAU,GAAGA,CAAO,GAAG,IAAI,OAAOC,CAAE,CAAC,GAAG,UAAU,EAAGA,CAAE,EAChDD,IAAY,GACf,GAAGM,CAAW,GAAGP,CAAO,GACxB,GAAGO,CAAW,GAAGP,CAAO,IAAIC,CAAO,EACzC,CAQO,SAASJ,EAAYR,EAAuB,CACjD,OAAOA,EAAM,QAAQ,KAAM,EAAE,CAC/B,CAUO,SAASmB,EAAcnB,EAAeoB,EAAwB,CAEnE,OAAO,IAAI,KAAK,aAAaA,EAAQ,CAAE,SAAU,SAAA,CAAW,EAAE,OAAO,OAAO,GAAGpB,EAAO,EAAE,EAAI,EAAIA,CAAK,CACvG,CA0CO,SAASqB,EAAKC,EAA+CC,EAAiCrB,EAG1F,CACT,IAAIU,EAAU,IAAIjB,EAAAA,QAAQ2B,CAAY,EACtC,UAAWE,KAAQD,EACjBX,EAAUA,EAAQY,EAAK,QAAQ,EAAEA,EAAK,KAAK,EAE7C,OAAItB,GAAS,OAAS,OACpBU,EAAUA,EAAQ,MAAMV,EAAQ,MAAOA,EAAQ,cAAgBc,EAAAA,cAAc,WAAW,GAEnFJ,EAAQ,SAAA,CACjB,CAWO,SAASa,EAAIC,KAA4CC,EAAqD,CACnH,IAAIf,EAAU,IAAIjB,EAAAA,QAAQ+B,CAAM,EAChC,UAAW1B,KAAS2B,EAClBf,EAAUA,EAAQ,IAAIZ,CAAK,EAE7B,OAAOY,EAAQ,SAAA,CACjB,CAWO,SAASgB,EAAIF,KAA4CC,EAAqD,CACnH,IAAIf,EAAU,IAAIjB,EAAAA,QAAQ+B,CAAM,EAChC,UAAW1B,KAAS2B,EAClBf,EAAUA,EAAQ,IAAIZ,CAAK,EAE7B,OAAOY,EAAQ,SAAA,CACjB,CAYO,SAASiB,EAAMH,KAA4CC,EAAqD,CACrH,IAAIf,EAAU,IAAIjB,EAAAA,QAAQ+B,CAAM,EAChC,UAAW1B,KAAS2B,EAClBf,EAAUA,EAAQ,MAAMZ,CAAK,EAE/B,OAAOY,EAAQ,SAAA,CACjB,CAYO,SAASkB,EAAIJ,KAA4CC,EAAqD,CACnH,IAAIf,EAAU,IAAIjB,EAAAA,QAAQ+B,CAAM,EAChC,UAAW1B,KAAS2B,EAClBf,EAAUA,EAAQ,IAAIZ,CAAK,EAE7B,OAAOY,EAAQ,SAAA,CACjB,CAWO,SAASmB,EAAUL,EAAyCC,EAAqD,CACtH,OAAO,IAAIhC,EAAAA,QAAQ+B,CAAM,EAAE,UAAUC,CAAM,CAC7C,CAWO,SAASK,EAAGN,EAAyCC,EAAkD,CAC5G,OAAOI,EAAUL,EAAQC,CAAM,IAAM,CACvC,CAWO,SAASM,EAAGP,EAAyCC,EAAkD,CAC5G,OAAOI,EAAUL,EAAQC,CAAM,EAAI,CACrC,CAWO,SAASO,EAAIR,EAAyCC,EAAkD,CAC7G,OAAOI,EAAUL,EAAQC,CAAM,GAAK,CACtC,CAWO,SAASQ,EAAGT,EAAyCC,EAAkD,CAC5G,MAAO,GAAII,EAAUL,EAAQC,CAAM,CACrC,CAWO,SAASS,EAAIV,EAAyCC,EAAkD,CAC7G,MAAO,IAAKI,EAAUL,EAAQC,CAAM,CACtC,CAkBO,SAASU,EACdrC,EACAK,EACAC,EACe,CACf,GAAIN,GAAS,KACX,OAAO,KAET,MAAMsC,EAAKhC,GAAgBU,EAAAA,cAAc,YACzC,OAAQ,OAAOhB,EAAA,CACb,IAAK,SACH,OAAK,OAAO,SAASA,CAAK,EAInB,IAAIL,EAAAA,QAAQK,CAAK,EAAE,MAAMK,EAAOiC,CAAE,EAAE,SAAA,EAFlCtC,EAGX,IAAK,SAAU,CACb,GAAID,EAAQC,CAAK,EAEf,OAAO,KAET,GAAI,CACF,OAAO,IAAIL,EAAAA,QAAQK,CAAK,EAAE,MAAMK,EAAOiC,CAAE,EAAE,SAAA,CAC7C,MAAgB,CAEd,OAAO,OAAO,GAChB,CACF,CACA,QACE,OAAO,IAAI3C,EAAAA,QAAQK,CAAK,EAAE,MAAMK,EAAOiC,CAAE,EAAE,SAAA,CAAS,CAE1D,CAcO,SAASC,EACdvC,EACAE,EAIQ,CACR,GAAIF,GAAS,KACX,MAAO,GAET,GAAID,EAAQC,CAAK,GAAM,OAAOA,GAAU,UAAY,CAAC,OAAO,SAASA,CAAK,EAExE,OAAO,OAAOA,CAAK,EAErB,GAAI,CACF,MAAMY,EAAU,IAAIjB,EAAAA,QAAQK,CAAK,EACjC,OAAOE,GAAS,OAAS,KACrBU,EAAQ,QAAQV,EAAQ,MAAOA,EAAQ,cAAgBc,EAAAA,cAAc,WAAW,EAChFJ,EAAQ,SAAA,CACd,MAAgB,CACd,OAAO,OAAOZ,CAAK,CACrB,CACF,CAgCO,SAASwC,EAA2DxC,EAAwCE,EAAqD,CAEtK,GAAIF,GAAS,MAAQD,EAAQC,CAAK,EAChC,OAAQE,GAAS,MAAA,CACf,IAAK,YACH,OACF,IAAK,OACH,MAAO,GACT,QACE,OAAO,IAAA,CAGb,IAAIuC,EACJ,OAAQ,OAAOzC,EAAA,CACb,IAAK,SACHyC,EAASzC,EACT,MACF,IAAK,SACHyC,EAAS,OAAOzC,CAAK,EACrB,MACF,IAAK,SACHyC,EAAS,OAAOjC,EAAYR,CAAK,EAAE,MAAM,EACzC,MACF,QAEEyC,EAASzC,EAAM,SAAA,CAAS,CAE5B,GAAI,OAAO,MAAMyC,CAAM,EACrB,OAAQvC,GAAS,IAAA,CACf,IAAK,OACH,OAAO,KACT,IAAK,YACH,OACF,QACE,OAAOuC,CAAA,CAGb,OAAOA,CACT,CAYO,SAASC,EACdC,EACAzC,EAKkB,CAClB,GAAIyC,GAAS,MAAQA,IAAU,GAC7B,MAAO,CAAC,OAAOA,CAAK,EAAG,EAAE,EAE3B,IAAI7B,EACJ,OAAQ,OAAO6B,EAAA,CACb,IAAK,SACH,GAAI,OAAO,MAAMA,CAAK,EAEpB,MAAO,CAAC,MAAO,EAAE,EAEnB7B,EAAe,IAAInB,EAAAA,QAAQgD,CAAK,EAChC,MACF,IAAK,SACH,GAAI,CACF7B,EAAe,IAAInB,EAAAA,QAAQa,EAAYmC,CAAK,CAAC,CAC/C,MAAgB,CAEd,MAAO,CAACA,EAAO,EAAE,CACnB,CACA,MACF,QAEE7B,EAAe,IAAInB,EAAAA,QAAQgD,CAAK,CAAA,CAEpC,MAAMC,EAAQ,CAAC,IAAK,KAAM,KAAM,KAAM,IAAI,EAC1C,IAAIC,EAAI,EACR,KAAO/B,EAAa,IAAI,IAAI,GAAK+B,EAAID,EAAM,OAAS,GAClD9B,EAAeA,EAAa,IAAI,IAAI,EACpC+B,IAEF,MAAMxC,EAAQH,GAAS,OAAS,EAC1BI,EAAeJ,GAAS,cAAgBc,EAAAA,cAAc,YAC5D,OAAId,GAAS,OACJ,CAACE,EAAYU,EAAa,SAAA,EAAYT,EAAOC,CAAY,EAAGsC,EAAMC,CAAC,CAAC,EAEtE,CAAC/B,EAAa,MAAMT,EAAOC,CAAY,EAAE,SAAA,EAAYsC,EAAMC,CAAC,CAAC,CACtE"}