@northguild/gmt 1.18.0 → 1.19.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.
- package/README.md +55 -2920
- package/dist/calendar/calculate/bucketRange.d.ts +10 -2
- package/dist/calendar/calculate/bucketRange.js +18 -61
- package/dist/calendar/calculate/floorToZone.d.ts +10 -2
- package/dist/calendar/calculate/floorToZone.js +15 -7
- package/dist/calendar/hours/addOperatingTime.d.ts +6 -0
- package/dist/calendar/hours/addOperatingTime.js +7 -1
- package/dist/calendar/hours/isOpenAt.d.ts +6 -0
- package/dist/calendar/hours/isOpenAt.js +6 -0
- package/dist/calendar/hours/nextCloseAt.d.ts +6 -0
- package/dist/calendar/hours/nextCloseAt.js +7 -1
- package/dist/calendar/hours/nextOpenAt.d.ts +6 -0
- package/dist/calendar/hours/nextOpenAt.js +7 -1
- package/dist/calendar/hours/operatingIntervals.d.ts +5 -0
- package/dist/calendar/hours/operatingIntervals.js +5 -0
- package/dist/calendar/hours/operatingTimeBetween.d.ts +5 -0
- package/dist/calendar/hours/operatingTimeBetween.js +5 -0
- package/dist/calendar/hours/recurringWindows.d.ts +8 -1
- package/dist/calendar/hours/recurringWindows.js +12 -4
- package/dist/duration/calculate/durationFromUnits.d.ts +47 -0
- package/dist/duration/calculate/durationFromUnits.js +67 -0
- package/dist/duration/calculate/getDurationUnit.d.ts +2 -2
- package/dist/duration/calculate/getDurationUnit.js +2 -2
- package/dist/duration/calculate/index.d.ts +3 -1
- package/dist/duration/calculate/index.js +3 -1
- package/dist/duration/calculate/negateDuration.d.ts +1 -1
- package/dist/duration/calculate/negateDuration.js +1 -1
- package/dist/duration/calculate/{durationAs.d.ts → totalDuration.d.ts} +25 -19
- package/dist/duration/calculate/{durationAs.js → totalDuration.js} +25 -19
- package/dist/duration/calculate/totalUnits.d.ts +49 -0
- package/dist/duration/calculate/totalUnits.js +73 -0
- package/dist/duration/compare/compareDurations.d.ts +1 -1
- package/dist/duration/compare/compareDurations.js +1 -1
- package/dist/duty/calculate/dutyDayFor.d.ts +38 -0
- package/dist/duty/calculate/dutyDayFor.js +71 -0
- package/dist/duty/calculate/dutyTotals.d.ts +24 -0
- package/dist/duty/calculate/dutyTotals.js +41 -0
- package/dist/duty/calculate/dutyViolations.d.ts +74 -0
- package/dist/duty/calculate/dutyViolations.js +65 -0
- package/dist/duty/calculate/evaluateDutyLog.d.ts +77 -0
- package/dist/duty/calculate/evaluateDutyLog.js +75 -0
- package/dist/duty/calculate/index.d.ts +7 -0
- package/dist/duty/calculate/index.js +7 -0
- package/dist/duty/calculate/longestRun.d.ts +28 -0
- package/dist/duty/calculate/longestRun.js +54 -0
- package/dist/duty/calculate/qualifyingRestPairs.d.ts +37 -0
- package/dist/duty/calculate/qualifyingRestPairs.js +58 -0
- package/dist/duty/calculate/qualifyingRests.d.ts +27 -0
- package/dist/duty/calculate/qualifyingRests.js +49 -0
- package/dist/duty/index.d.ts +3 -0
- package/dist/duty/index.js +4 -0
- package/dist/duty/validate/index.d.ts +1 -0
- package/dist/duty/validate/index.js +1 -0
- package/dist/duty/validate/isValidDutyLog.d.ts +24 -0
- package/dist/duty/validate/isValidDutyLog.js +34 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/instant/convert/classifyLocal.d.ts +5 -1
- package/dist/instant/convert/classifyLocal.js +16 -6
- package/dist/instant/convert/fromOffsetInstant.d.ts +4 -0
- package/dist/instant/convert/fromOffsetInstant.js +6 -1
- package/dist/instant/convert/resolveLocal.d.ts +7 -2
- package/dist/instant/convert/resolveLocal.js +16 -8
- package/dist/instant/convert/toOffsetInstant.d.ts +12 -8
- package/dist/instant/convert/toOffsetInstant.js +19 -11
- package/dist/instant/index.d.ts +1 -0
- package/dist/instant/index.js +1 -0
- package/dist/instant/validate/index.d.ts +1 -0
- package/dist/instant/validate/index.js +1 -0
- package/dist/instant/validate/isValidUtcOffset.d.ts +32 -0
- package/dist/instant/validate/isValidUtcOffset.js +35 -0
- package/dist/intermodal/calculate/chargeableDays.d.ts +6 -0
- package/dist/intermodal/calculate/chargeableDays.js +12 -4
- package/dist/intermodal/calculate/freeTimeExpiry.d.ts +7 -0
- package/dist/intermodal/calculate/freeTimeExpiry.js +15 -4
- package/dist/intermodal/calculate/index.d.ts +1 -0
- package/dist/intermodal/calculate/index.js +1 -0
- package/dist/intermodal/calculate/multimodalETA.d.ts +76 -0
- package/dist/intermodal/calculate/multimodalETA.js +145 -0
- package/dist/intermodal/format/bolTimestamp.d.ts +76 -0
- package/dist/intermodal/format/bolTimestamp.js +78 -0
- package/dist/intermodal/format/formatEdifactDate.d.ts +34 -0
- package/dist/intermodal/format/formatEdifactDate.js +42 -0
- package/dist/intermodal/format/formatEdifactDatePeriod.d.ts +35 -0
- package/dist/intermodal/format/formatEdifactDatePeriod.js +43 -0
- package/dist/intermodal/format/formatEdifactDateTime.d.ts +37 -0
- package/dist/intermodal/format/formatEdifactDateTime.js +45 -0
- package/dist/intermodal/format/formatEdifactDateTimePeriod.d.ts +40 -0
- package/dist/intermodal/format/formatEdifactDateTimePeriod.js +48 -0
- package/dist/intermodal/format/formatEdifactOffsetDateTime.d.ts +62 -0
- package/dist/intermodal/format/formatEdifactOffsetDateTime.js +70 -0
- package/dist/intermodal/format/formatEdifactTime.d.ts +35 -0
- package/dist/intermodal/format/formatEdifactTime.js +43 -0
- package/dist/intermodal/format/formatEpcisEvent.d.ts +47 -0
- package/dist/intermodal/format/formatEpcisEvent.js +79 -0
- package/dist/intermodal/format/formatX12Date.d.ts +35 -0
- package/dist/intermodal/format/formatX12Date.js +43 -0
- package/dist/intermodal/format/formatX12DateRange.d.ts +37 -0
- package/dist/intermodal/format/formatX12DateRange.js +45 -0
- package/dist/intermodal/format/formatX12DateTime.d.ts +39 -0
- package/dist/intermodal/format/formatX12DateTime.js +47 -0
- package/dist/intermodal/format/formatX12DateTimeRange.d.ts +40 -0
- package/dist/intermodal/format/formatX12DateTimeRange.js +48 -0
- package/dist/intermodal/format/formatX12Time.d.ts +42 -0
- package/dist/intermodal/format/formatX12Time.js +50 -0
- package/dist/intermodal/format/formatX12TimeElement.d.ts +46 -0
- package/dist/intermodal/format/formatX12TimeElement.js +54 -0
- package/dist/intermodal/format/index.d.ts +14 -0
- package/dist/intermodal/format/index.js +14 -0
- package/dist/intermodal/index.d.ts +3 -0
- package/dist/intermodal/index.js +3 -0
- package/dist/intermodal/parse/classifyEdifactDtmFormat.d.ts +48 -0
- package/dist/intermodal/parse/classifyEdifactDtmFormat.js +55 -0
- package/dist/intermodal/parse/classifyX12DateTimePeriodFormat.d.ts +50 -0
- package/dist/intermodal/parse/classifyX12DateTimePeriodFormat.js +57 -0
- package/dist/intermodal/parse/classifyX12TimeCode.d.ts +46 -0
- package/dist/intermodal/parse/classifyX12TimeCode.js +57 -0
- package/dist/intermodal/parse/index.d.ts +18 -0
- package/dist/intermodal/parse/index.js +18 -0
- package/dist/intermodal/parse/parseEdifactDate.d.ts +37 -0
- package/dist/intermodal/parse/parseEdifactDate.js +45 -0
- package/dist/intermodal/parse/parseEdifactDatePeriod.d.ts +43 -0
- package/dist/intermodal/parse/parseEdifactDatePeriod.js +51 -0
- package/dist/intermodal/parse/parseEdifactDateTime.d.ts +43 -0
- package/dist/intermodal/parse/parseEdifactDateTime.js +51 -0
- package/dist/intermodal/parse/parseEdifactDateTimePeriod.d.ts +45 -0
- package/dist/intermodal/parse/parseEdifactDateTimePeriod.js +53 -0
- package/dist/intermodal/parse/parseEdifactOffsetDateTime.d.ts +60 -0
- package/dist/intermodal/parse/parseEdifactOffsetDateTime.js +68 -0
- package/dist/intermodal/parse/parseEdifactTime.d.ts +37 -0
- package/dist/intermodal/parse/parseEdifactTime.js +45 -0
- package/dist/intermodal/parse/parseEpcisEvent.d.ts +95 -0
- package/dist/intermodal/parse/parseEpcisEvent.js +102 -0
- package/dist/intermodal/parse/parseX12Date.d.ts +39 -0
- package/dist/intermodal/parse/parseX12Date.js +47 -0
- package/dist/intermodal/parse/parseX12DateAndTime.d.ts +52 -0
- package/dist/intermodal/parse/parseX12DateAndTime.js +61 -0
- package/dist/intermodal/parse/parseX12DateRange.d.ts +44 -0
- package/dist/intermodal/parse/parseX12DateRange.js +52 -0
- package/dist/intermodal/parse/parseX12DateTime.d.ts +45 -0
- package/dist/intermodal/parse/parseX12DateTime.js +53 -0
- package/dist/intermodal/parse/parseX12DateTimeRange.d.ts +46 -0
- package/dist/intermodal/parse/parseX12DateTimeRange.js +54 -0
- package/dist/intermodal/parse/parseX12Time.d.ts +65 -0
- package/dist/intermodal/parse/parseX12Time.js +77 -0
- package/dist/intermodal/parse/x12TimeCodeOffset.d.ts +57 -0
- package/dist/intermodal/parse/x12TimeCodeOffset.js +110 -0
- package/dist/intermodal/parse/x12TimeCodeZone.d.ts +57 -0
- package/dist/intermodal/parse/x12TimeCodeZone.js +105 -0
- package/dist/intermodal/validate/index.d.ts +18 -0
- package/dist/intermodal/validate/index.js +18 -0
- package/dist/intermodal/validate/isValidEdifactDate.d.ts +26 -0
- package/dist/intermodal/validate/isValidEdifactDate.js +28 -0
- package/dist/intermodal/validate/isValidEdifactDatePeriod.d.ts +28 -0
- package/dist/intermodal/validate/isValidEdifactDatePeriod.js +30 -0
- package/dist/intermodal/validate/isValidEdifactDateTime.d.ts +30 -0
- package/dist/intermodal/validate/isValidEdifactDateTime.js +32 -0
- package/dist/intermodal/validate/isValidEdifactDateTimePeriod.d.ts +28 -0
- package/dist/intermodal/validate/isValidEdifactDateTimePeriod.js +30 -0
- package/dist/intermodal/validate/isValidEdifactDtmFormat.d.ts +39 -0
- package/dist/intermodal/validate/isValidEdifactDtmFormat.js +42 -0
- package/dist/intermodal/validate/isValidEdifactOffsetDateTime.d.ts +36 -0
- package/dist/intermodal/validate/isValidEdifactOffsetDateTime.js +38 -0
- package/dist/intermodal/validate/isValidEdifactTime.d.ts +28 -0
- package/dist/intermodal/validate/isValidEdifactTime.js +30 -0
- package/dist/intermodal/validate/isValidEpcisEvent.d.ts +41 -0
- package/dist/intermodal/validate/isValidEpcisEvent.js +58 -0
- package/dist/intermodal/validate/isValidEpcisEventTime.d.ts +33 -0
- package/dist/intermodal/validate/isValidEpcisEventTime.js +48 -0
- package/dist/intermodal/validate/isValidEpcisTimeZoneOffset.d.ts +30 -0
- package/dist/intermodal/validate/isValidEpcisTimeZoneOffset.js +38 -0
- package/dist/intermodal/validate/isValidX12Date.d.ts +28 -0
- package/dist/intermodal/validate/isValidX12Date.js +30 -0
- package/dist/intermodal/validate/isValidX12DateAndTime.d.ts +32 -0
- package/dist/intermodal/validate/isValidX12DateAndTime.js +35 -0
- package/dist/intermodal/validate/isValidX12DateRange.d.ts +29 -0
- package/dist/intermodal/validate/isValidX12DateRange.js +31 -0
- package/dist/intermodal/validate/isValidX12DateTime.d.ts +30 -0
- package/dist/intermodal/validate/isValidX12DateTime.js +32 -0
- package/dist/intermodal/validate/isValidX12DateTimePeriodFormat.d.ts +43 -0
- package/dist/intermodal/validate/isValidX12DateTimePeriodFormat.js +46 -0
- package/dist/intermodal/validate/isValidX12DateTimeRange.d.ts +31 -0
- package/dist/intermodal/validate/isValidX12DateTimeRange.js +33 -0
- package/dist/intermodal/validate/isValidX12Time.d.ts +38 -0
- package/dist/intermodal/validate/isValidX12Time.js +40 -0
- package/dist/intermodal/validate/isValidX12TimeCode.d.ts +38 -0
- package/dist/intermodal/validate/isValidX12TimeCode.js +41 -0
- package/dist/internal/businessCalendar.js +4 -9
- package/dist/internal/dutyEngine.d.ts +125 -0
- package/dist/internal/dutyEngine.js +1746 -0
- package/dist/internal/dutyLog.d.ts +27 -0
- package/dist/internal/dutyLog.js +47 -0
- package/dist/internal/dutyPeriods.d.ts +135 -0
- package/dist/internal/dutyPeriods.js +369 -0
- package/dist/internal/dutyRules.d.ts +197 -0
- package/dist/internal/dutyRules.js +484 -0
- package/dist/internal/ediDateTimeFields.d.ts +97 -0
- package/dist/internal/ediDateTimeFields.js +288 -0
- package/dist/internal/ediDateTimeWriter.d.ts +92 -0
- package/dist/internal/ediDateTimeWriter.js +298 -0
- package/dist/internal/ediGrammar.d.ts +158 -0
- package/dist/internal/ediGrammar.js +384 -0
- package/dist/internal/englishCalendarNames.d.ts +3 -1
- package/dist/internal/englishCalendarNames.js +3 -1
- package/dist/internal/freeTimeLedger.d.ts +5 -0
- package/dist/internal/freeTimeLedger.js +11 -2
- package/dist/internal/index.d.ts +5 -2
- package/dist/internal/index.js +9 -2
- package/dist/internal/intervalNanoseconds.js +2 -1
- package/dist/internal/isObject.d.ts +13 -6
- package/dist/internal/isObject.js +14 -7
- package/dist/internal/isoYearString.d.ts +21 -0
- package/dist/internal/isoYearString.js +27 -0
- package/dist/internal/maxPieces.js +2 -1
- package/dist/internal/normalizeTimeZone.d.ts +4 -1
- package/dist/internal/normalizeTimeZone.js +4 -1
- package/dist/internal/operatingSchedule.d.ts +13 -4
- package/dist/internal/operatingSchedule.js +146 -58
- package/dist/internal/patternToken.d.ts +10 -3
- package/dist/internal/patternToken.js +31 -12
- package/dist/internal/readDurationUnits.d.ts +34 -0
- package/dist/internal/readDurationUnits.js +78 -0
- package/dist/internal/readSetFields.d.ts +50 -0
- package/dist/internal/readSetFields.js +179 -0
- package/dist/internal/resolveRelativeUnit.d.ts +1 -1
- package/dist/internal/resolveRelativeUnit.js +1 -1
- package/dist/internal/resolveUnixIntervalPair.d.ts +8 -2
- package/dist/internal/resolveUnixIntervalPair.js +11 -7
- package/dist/internal/startOrEndOfUnix.d.ts +2 -1
- package/dist/internal/startOrEndOfUnix.js +9 -6
- package/dist/internal/twoDigitYear.d.ts +19 -0
- package/dist/internal/twoDigitYear.js +22 -0
- package/dist/internal/unixEpochValue.js +3 -2
- package/dist/internal/unixWallClock.d.ts +24 -0
- package/dist/internal/unixWallClock.js +35 -0
- package/dist/internal/utcWallClock.d.ts +20 -0
- package/dist/internal/utcWallClock.js +32 -0
- package/dist/internal/yearWindowStart.d.ts +28 -0
- package/dist/internal/yearWindowStart.js +52 -0
- package/dist/internal/zoneBucketCap.d.ts +18 -0
- package/dist/internal/zoneBucketCap.js +64 -0
- package/dist/internal/zoneFrame.d.ts +180 -0
- package/dist/internal/zoneFrame.js +221 -0
- package/dist/internal/zonedNowUnitValue.d.ts +7 -4
- package/dist/internal/zonedNowUnitValue.js +8 -4
- package/dist/internal/zonedWallClockDifference.js +4 -4
- package/dist/internal/zonedWallClockOperations.d.ts +5 -2
- package/dist/internal/zonedWallClockOperations.js +7 -10
- package/dist/plain/calculate/addDate.js +4 -7
- package/dist/plain/calculate/addDateTime.js +4 -7
- package/dist/plain/calculate/addTime.js +4 -7
- package/dist/plain/calculate/endOfTime.d.ts +1 -1
- package/dist/plain/calculate/setDate.d.ts +20 -3
- package/dist/plain/calculate/setDate.js +27 -7
- package/dist/plain/calculate/setDateTime.d.ts +15 -3
- package/dist/plain/calculate/setDateTime.js +22 -7
- package/dist/plain/calculate/setTime.d.ts +13 -1
- package/dist/plain/calculate/setTime.js +21 -6
- package/dist/plain/calculate/startOfTime.d.ts +1 -1
- package/dist/plain/calculate/subtractDate.js +4 -7
- package/dist/plain/calculate/subtractDateTime.js +4 -7
- package/dist/plain/calculate/subtractTime.js +4 -7
- package/dist/plain/format/formatCalendar.js +2 -1
- package/dist/plain/format/formatRelativeDate.js +2 -1
- package/dist/plain/format/formatRelativeDateTime.js +2 -1
- package/dist/plain/format/formatRelativeTime.js +2 -1
- package/dist/plain/format/{formatSql.d.ts → formatSqlDateTime.d.ts} +7 -7
- package/dist/plain/format/{formatSql.js → formatSqlDateTime.js} +7 -7
- package/dist/plain/format/index.d.ts +1 -1
- package/dist/plain/format/index.js +1 -1
- package/dist/plain/get/getNowUnit.d.ts +2 -0
- package/dist/plain/get/getNowUnit.js +2 -0
- package/dist/plain/get/getYear.d.ts +2 -0
- package/dist/plain/get/getYear.js +4 -3
- package/dist/plain/interval/intervalXorAllDate.js +2 -2
- package/dist/plain/interval/intervalXorAllDateTime.js +2 -2
- package/dist/plain/interval/intervalXorAllTime.js +2 -2
- package/dist/plain/interval/mergeIntervalsDate.js +2 -2
- package/dist/plain/interval/mergeIntervalsDateTime.js +2 -2
- package/dist/plain/interval/mergeIntervalsTime.js +2 -2
- package/dist/plain/parse/index.d.ts +1 -1
- package/dist/plain/parse/index.js +1 -1
- package/dist/plain/parse/parseDateTimeWithPattern.d.ts +16 -3
- package/dist/plain/parse/parseDateTimeWithPattern.js +20 -5
- package/dist/plain/parse/parseDateWithPattern.d.ts +17 -3
- package/dist/plain/parse/parseDateWithPattern.js +21 -5
- package/dist/plain/parse/{parseSql.d.ts → parseSqlDateTime.d.ts} +8 -8
- package/dist/plain/parse/{parseSql.js → parseSqlDateTime.js} +8 -8
- package/dist/plain/parse/parseTimeWithPattern.js +1 -0
- package/dist/plain/parse/parseUnitFromDate.d.ts +3 -0
- package/dist/plain/parse/parseUnitFromDate.js +5 -1
- package/dist/plain/parse/parseUnitFromDateTime.d.ts +3 -0
- package/dist/plain/parse/parseUnitFromDateTime.js +5 -1
- package/dist/plain/parse/parseYearFromDate.d.ts +5 -2
- package/dist/plain/parse/parseYearFromDate.js +7 -3
- package/dist/plain/parse/parseYearFromDateTime.d.ts +4 -2
- package/dist/plain/parse/parseYearFromDateTime.js +6 -3
- package/dist/plain/validate/index.d.ts +1 -0
- package/dist/plain/validate/index.js +1 -0
- package/dist/plain/validate/isValidSqlDateTime.d.ts +33 -0
- package/dist/plain/validate/isValidSqlDateTime.js +36 -0
- package/dist/precision/convert/fromNanoseconds.d.ts +9 -3
- package/dist/precision/convert/fromNanoseconds.js +9 -3
- package/dist/regex/epcis.d.ts +60 -0
- package/dist/regex/epcis.js +60 -0
- package/dist/regex/http-date.d.ts +6 -4
- package/dist/regex/http-date.js +6 -4
- package/dist/regex/index.d.ts +1 -0
- package/dist/regex/index.js +1 -0
- package/dist/regex/rfc-2822.d.ts +2 -0
- package/dist/regex/rfc-2822.js +2 -0
- package/dist/regex/rfc-3339.d.ts +3 -1
- package/dist/regex/rfc-3339.js +3 -1
- package/dist/regex/sql-date-time.d.ts +2 -1
- package/dist/regex/sql-date-time.js +2 -1
- package/dist/regex/time-zone-like.d.ts +3 -2
- package/dist/regex/time-zone-like.js +3 -2
- package/dist/regex/utc-offset.d.ts +2 -1
- package/dist/regex/utc-offset.js +2 -1
- package/dist/transport/calculate/crossingTime.d.ts +6 -1
- package/dist/transport/calculate/crossingTime.js +6 -1
- package/dist/transport/calculate/cutoffAt.d.ts +6 -1
- package/dist/transport/calculate/cutoffAt.js +2 -0
- package/dist/transport/calculate/cutoffSchedule.d.ts +6 -1
- package/dist/transport/calculate/cutoffSchedule.js +2 -0
- package/dist/transport/calculate/dwellTime.d.ts +6 -1
- package/dist/transport/calculate/dwellTime.js +6 -1
- package/dist/transport/calculate/scheduleDelivery.d.ts +13 -5
- package/dist/transport/calculate/scheduleDelivery.js +6 -1
- package/dist/transport/convert/etaAtZone.d.ts +6 -1
- package/dist/transport/convert/etaAtZone.js +6 -1
- package/dist/types/business-calendar.d.ts +5 -4
- package/dist/types/duty.d.ts +777 -0
- package/dist/types/duty.js +0 -0
- package/dist/types/edi.d.ts +407 -0
- package/dist/types/edi.js +0 -0
- package/dist/types/epcis.d.ts +25 -0
- package/dist/types/epcis.js +0 -0
- package/dist/types/exact-duration-unit.d.ts +8 -0
- package/dist/types/exact-duration-unit.js +0 -0
- package/dist/types/free-time-options.d.ts +4 -3
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +5 -0
- package/dist/types/operating-schedule.d.ts +3 -2
- package/dist/types/two-digit-year.d.ts +23 -0
- package/dist/types/two-digit-year.js +0 -0
- package/dist/types/zone-bucket-unit.d.ts +1 -1
- package/dist/unix/calculate/addUnix.d.ts +11 -2
- package/dist/unix/calculate/addUnix.js +14 -11
- package/dist/unix/calculate/diffUnix.d.ts +10 -2
- package/dist/unix/calculate/diffUnix.js +11 -6
- package/dist/unix/calculate/diffUnixAsDuration.d.ts +10 -2
- package/dist/unix/calculate/diffUnixAsDuration.js +10 -5
- package/dist/unix/calculate/endOfQuarterForUnix.d.ts +10 -2
- package/dist/unix/calculate/endOfQuarterForUnix.js +6 -0
- package/dist/unix/calculate/endOfUnix.d.ts +11 -2
- package/dist/unix/calculate/endOfUnix.js +7 -0
- package/dist/unix/calculate/isBetweenUnix.d.ts +3 -2
- package/dist/unix/calculate/isBetweenUnix.js +3 -3
- package/dist/unix/calculate/roundUnix.d.ts +10 -2
- package/dist/unix/calculate/roundUnix.js +13 -6
- package/dist/unix/calculate/setUnix.d.ts +25 -5
- package/dist/unix/calculate/setUnix.js +33 -12
- package/dist/unix/calculate/startOfQuarterForUnix.d.ts +10 -2
- package/dist/unix/calculate/startOfQuarterForUnix.js +6 -0
- package/dist/unix/calculate/startOfUnix.d.ts +11 -2
- package/dist/unix/calculate/startOfUnix.js +7 -0
- package/dist/unix/calculate/subtractUnix.d.ts +10 -2
- package/dist/unix/calculate/subtractUnix.js +13 -11
- package/dist/unix/compare/areUnixEqualBy.d.ts +11 -2
- package/dist/unix/compare/areUnixEqualBy.js +7 -0
- package/dist/unix/convert/convertUnixToPlainDate.d.ts +5 -2
- package/dist/unix/convert/convertUnixToPlainDate.js +5 -4
- package/dist/unix/convert/convertUnixToPlainDateTime.d.ts +5 -2
- package/dist/unix/convert/convertUnixToPlainDateTime.js +5 -4
- package/dist/unix/convert/convertUnixToPlainTime.d.ts +5 -2
- package/dist/unix/convert/convertUnixToPlainTime.js +5 -4
- package/dist/unix/convert/convertUnixToZoned.d.ts +5 -1
- package/dist/unix/convert/convertUnixToZoned.js +5 -1
- package/dist/unix/format/formatCalendarUnix.d.ts +6 -2
- package/dist/unix/format/formatCalendarUnix.js +6 -1
- package/dist/unix/format/formatRelativeUnix.d.ts +11 -3
- package/dist/unix/format/formatRelativeUnix.js +13 -5
- package/dist/unix/format/formatUnix.d.ts +7 -2
- package/dist/unix/format/formatUnix.js +4 -0
- package/dist/unix/get/getUnixDay.d.ts +1 -3
- package/dist/unix/get/getUnixDay.js +5 -12
- package/dist/unix/get/getUnixHour.d.ts +1 -3
- package/dist/unix/get/getUnixHour.js +5 -12
- package/dist/unix/get/getUnixMicrosecond.d.ts +1 -3
- package/dist/unix/get/getUnixMicrosecond.js +4 -11
- package/dist/unix/get/getUnixMillisecond.d.ts +1 -3
- package/dist/unix/get/getUnixMillisecond.js +5 -12
- package/dist/unix/get/getUnixMinute.d.ts +1 -3
- package/dist/unix/get/getUnixMinute.js +5 -12
- package/dist/unix/get/getUnixMonth.d.ts +1 -3
- package/dist/unix/get/getUnixMonth.js +5 -12
- package/dist/unix/get/getUnixNanosecond.d.ts +1 -3
- package/dist/unix/get/getUnixNanosecond.js +4 -11
- package/dist/unix/get/getUnixNowUnit.d.ts +2 -0
- package/dist/unix/get/getUnixNowUnit.js +2 -0
- package/dist/unix/get/getUnixSecond.d.ts +1 -3
- package/dist/unix/get/getUnixSecond.js +5 -12
- package/dist/unix/get/getUnixYear.d.ts +3 -3
- package/dist/unix/get/getUnixYear.js +5 -12
- package/dist/unix/interval/intervalCountUnix.d.ts +11 -2
- package/dist/unix/interval/intervalCountUnix.js +7 -0
- package/dist/unix/interval/intervalFromDurationUnix.d.ts +10 -2
- package/dist/unix/interval/intervalFromDurationUnix.js +12 -7
- package/dist/unix/interval/intervalLengthUnix.d.ts +10 -2
- package/dist/unix/interval/intervalLengthUnix.js +6 -0
- package/dist/unix/interval/intervalOverlappingDaysUnix.d.ts +10 -2
- package/dist/unix/interval/intervalOverlappingDaysUnix.js +10 -5
- package/dist/unix/interval/splitIntervalByUnitUnix.d.ts +10 -2
- package/dist/unix/interval/splitIntervalByUnitUnix.js +12 -6
- package/dist/unix/parse/parseDateFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseDateFromUnix.js +3 -3
- package/dist/unix/parse/parseDayFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseDayOfWeekFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseDayOfWeekFromUnix.js +2 -2
- package/dist/unix/parse/parseHourFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseMicrosecondFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseMillisecondFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseMinuteFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseMonthFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseNanosecondFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseSecondFromUnix.d.ts +4 -2
- package/dist/unix/parse/parseTimeFromUnix.d.ts +5 -2
- package/dist/unix/parse/parseTimeFromUnix.js +4 -3
- package/dist/unix/parse/parseUnitFromUnix.d.ts +9 -3
- package/dist/unix/parse/parseUnitFromUnix.js +21 -14
- package/dist/unix/parse/parseWeekFromUnix.d.ts +3 -2
- package/dist/unix/parse/parseWeekFromUnix.js +4 -4
- package/dist/unix/parse/parseYearFromUnix.d.ts +8 -3
- package/dist/unix/parse/parseYearFromUnix.js +4 -1
- package/dist/unix/validate/isValidUnixUnit.d.ts +1 -1
- package/dist/utc/calculate/addUtc.js +4 -7
- package/dist/utc/calculate/setUtc.d.ts +16 -3
- package/dist/utc/calculate/setUtc.js +22 -8
- package/dist/utc/calculate/subtractUtc.js +4 -7
- package/dist/utc/convert/convertUtcToPlainDate.d.ts +8 -2
- package/dist/utc/convert/convertUtcToPlainDate.js +10 -7
- package/dist/utc/convert/convertUtcToPlainDateTime.d.ts +9 -2
- package/dist/utc/convert/convertUtcToPlainDateTime.js +12 -13
- package/dist/utc/convert/convertUtcToPlainTime.d.ts +5 -2
- package/dist/utc/convert/convertUtcToPlainTime.js +7 -6
- package/dist/utc/convert/convertUtcToZoned.d.ts +5 -1
- package/dist/utc/convert/convertUtcToZoned.js +5 -1
- package/dist/utc/format/formatCalendarUtc.d.ts +6 -2
- package/dist/utc/format/formatCalendarUtc.js +6 -1
- package/dist/utc/format/{formatHttp.d.ts → formatHttpDate.d.ts} +7 -7
- package/dist/utc/format/{formatHttp.js → formatHttpDate.js} +7 -7
- package/dist/utc/format/formatRelativeUtc.d.ts +11 -3
- package/dist/utc/format/formatRelativeUtc.js +13 -5
- package/dist/utc/format/formatUtc.d.ts +7 -2
- package/dist/utc/format/formatUtc.js +4 -0
- package/dist/utc/format/index.d.ts +1 -1
- package/dist/utc/format/index.js +1 -1
- package/dist/utc/get/getUtcDay.d.ts +1 -3
- package/dist/utc/get/getUtcDay.js +5 -12
- package/dist/utc/get/getUtcHour.d.ts +1 -3
- package/dist/utc/get/getUtcHour.js +5 -12
- package/dist/utc/get/getUtcMicrosecond.d.ts +1 -3
- package/dist/utc/get/getUtcMicrosecond.js +4 -11
- package/dist/utc/get/getUtcMillisecond.d.ts +1 -3
- package/dist/utc/get/getUtcMillisecond.js +5 -12
- package/dist/utc/get/getUtcMinute.d.ts +1 -3
- package/dist/utc/get/getUtcMinute.js +5 -12
- package/dist/utc/get/getUtcMonth.d.ts +1 -3
- package/dist/utc/get/getUtcMonth.js +5 -12
- package/dist/utc/get/getUtcNanosecond.d.ts +1 -3
- package/dist/utc/get/getUtcNanosecond.js +4 -11
- package/dist/utc/get/getUtcNow.d.ts +1 -3
- package/dist/utc/get/getUtcNow.js +2 -9
- package/dist/utc/get/getUtcNowUnit.d.ts +2 -0
- package/dist/utc/get/getUtcNowUnit.js +2 -0
- package/dist/utc/get/getUtcSecond.d.ts +1 -3
- package/dist/utc/get/getUtcSecond.js +5 -12
- package/dist/utc/get/getUtcYear.d.ts +3 -3
- package/dist/utc/get/getUtcYear.js +5 -12
- package/dist/utc/interval/intervalXorAllUtc.js +2 -2
- package/dist/utc/interval/mergeIntervalsUtc.js +2 -2
- package/dist/utc/parse/index.d.ts +1 -1
- package/dist/utc/parse/index.js +1 -1
- package/dist/utc/parse/parseDateFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseDateFromUtc.js +2 -2
- package/dist/utc/parse/parseDayFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseDayFromUtc.js +2 -2
- package/dist/utc/parse/parseDayOfWeekFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseDayOfWeekFromUtc.js +4 -4
- package/dist/utc/parse/parseHourFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseHourFromUtc.js +2 -2
- package/dist/utc/parse/{parseHttp.d.ts → parseHttpDate.d.ts} +12 -12
- package/dist/utc/parse/{parseHttp.js → parseHttpDate.js} +12 -12
- package/dist/utc/parse/parseMicrosecondFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseMicrosecondFromUtc.js +2 -2
- package/dist/utc/parse/parseMillisecondFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseMillisecondFromUtc.js +2 -2
- package/dist/utc/parse/parseMinuteFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseMinuteFromUtc.js +2 -2
- package/dist/utc/parse/parseMonthFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseMonthFromUtc.js +2 -2
- package/dist/utc/parse/parseNanosecondFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseNanosecondFromUtc.js +2 -2
- package/dist/utc/parse/parseSecondFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseSecondFromUtc.js +2 -2
- package/dist/utc/parse/parseTimeFromUtc.d.ts +5 -2
- package/dist/utc/parse/parseTimeFromUtc.js +5 -4
- package/dist/utc/parse/parseUnitFromUtc.d.ts +10 -3
- package/dist/utc/parse/parseUnitFromUtc.js +11 -5
- package/dist/utc/parse/parseWeekFromUtc.d.ts +4 -2
- package/dist/utc/parse/parseWeekFromUtc.js +4 -4
- package/dist/utc/parse/parseYearFromUtc.d.ts +8 -4
- package/dist/utc/parse/parseYearFromUtc.js +8 -5
- package/dist/utc/validate/index.d.ts +2 -0
- package/dist/utc/validate/index.js +2 -0
- package/dist/utc/validate/isValidHttpDate.d.ts +35 -0
- package/dist/utc/validate/isValidHttpDate.js +38 -0
- package/dist/utc/validate/isValidUtc.d.ts +4 -0
- package/dist/utc/validate/isValidUtc.js +4 -0
- package/dist/utc/validate/isValidUtcTimestamp.d.ts +43 -0
- package/dist/utc/validate/isValidUtcTimestamp.js +48 -0
- package/dist/zoned/calculate/addZoned.js +4 -7
- package/dist/zoned/calculate/setZoned.d.ts +19 -5
- package/dist/zoned/calculate/setZoned.js +26 -9
- package/dist/zoned/calculate/subtractZoned.js +4 -7
- package/dist/zoned/convert/convertPlainDateTimeToZoned.d.ts +4 -1
- package/dist/zoned/convert/convertPlainDateTimeToZoned.js +4 -1
- package/dist/zoned/convert/convertZonedToZoned.d.ts +5 -1
- package/dist/zoned/convert/convertZonedToZoned.js +5 -1
- package/dist/zoned/format/formatCalendarZoned.js +2 -1
- package/dist/zoned/format/formatRelativeZoned.js +2 -1
- package/dist/zoned/format/formatTimeZoneName.d.ts +5 -1
- package/dist/zoned/format/formatTimeZoneName.js +5 -1
- package/dist/zoned/get/getDstTransitions.d.ts +5 -3
- package/dist/zoned/get/getDstTransitions.js +12 -7
- package/dist/zoned/get/getSystemTimeZone.d.ts +3 -1
- package/dist/zoned/get/getSystemTimeZone.js +5 -2
- package/dist/zoned/get/getTimeZoneOffset.d.ts +10 -2
- package/dist/zoned/get/getTimeZoneOffset.js +18 -5
- package/dist/zoned/get/getZonedDay.d.ts +2 -1
- package/dist/zoned/get/getZonedDay.js +6 -7
- package/dist/zoned/get/getZonedDayOfWeek.d.ts +2 -1
- package/dist/zoned/get/getZonedDayOfWeek.js +6 -5
- package/dist/zoned/get/getZonedHour.d.ts +2 -1
- package/dist/zoned/get/getZonedHour.js +6 -7
- package/dist/zoned/get/getZonedMicrosecond.d.ts +2 -1
- package/dist/zoned/get/getZonedMicrosecond.js +6 -5
- package/dist/zoned/get/getZonedMillisecond.d.ts +2 -1
- package/dist/zoned/get/getZonedMillisecond.js +6 -7
- package/dist/zoned/get/getZonedMinute.d.ts +2 -1
- package/dist/zoned/get/getZonedMinute.js +6 -7
- package/dist/zoned/get/getZonedMonth.d.ts +2 -1
- package/dist/zoned/get/getZonedMonth.js +6 -7
- package/dist/zoned/get/getZonedNanosecond.d.ts +2 -1
- package/dist/zoned/get/getZonedNanosecond.js +6 -5
- package/dist/zoned/get/getZonedNow.d.ts +5 -1
- package/dist/zoned/get/getZonedNow.js +5 -1
- package/dist/zoned/get/getZonedNowUnit.d.ts +6 -3
- package/dist/zoned/get/getZonedNowUnit.js +10 -7
- package/dist/zoned/get/getZonedSecond.d.ts +2 -1
- package/dist/zoned/get/getZonedSecond.js +6 -7
- package/dist/zoned/get/getZonedToday.d.ts +2 -1
- package/dist/zoned/get/getZonedToday.js +6 -5
- package/dist/zoned/get/getZonedWeekOfYear.d.ts +2 -1
- package/dist/zoned/get/getZonedWeekOfYear.js +6 -5
- package/dist/zoned/get/getZonedYear.d.ts +4 -1
- package/dist/zoned/get/getZonedYear.js +9 -7
- package/dist/zoned/interval/intervalXorAllZoned.js +2 -2
- package/dist/zoned/interval/mergeIntervalsZoned.js +2 -2
- package/dist/zoned/parse/parseUnitFromZoned.d.ts +4 -1
- package/dist/zoned/parse/parseUnitFromZoned.js +5 -1
- package/dist/zoned/parse/parseYearFromZoned.d.ts +4 -2
- package/dist/zoned/parse/parseYearFromZoned.js +6 -3
- package/dist/zoned/validate/hasDaylightSaving.d.ts +4 -2
- package/dist/zoned/validate/hasDaylightSaving.js +13 -7
- package/dist/zoned/validate/index.d.ts +2 -0
- package/dist/zoned/validate/index.js +2 -0
- package/dist/zoned/validate/isValidRfc2822DateTime.d.ts +32 -0
- package/dist/zoned/validate/isValidRfc2822DateTime.js +35 -0
- package/dist/zoned/validate/isValidRfc3339DateTime.d.ts +31 -0
- package/dist/zoned/validate/isValidRfc3339DateTime.js +34 -0
- package/dist/zoned/validate/isValidTimeZone.d.ts +5 -1
- package/dist/zoned/validate/isValidTimeZone.js +6 -2
- package/package.json +50 -1
- package/skills/gmt-arithmetic/SKILL.md +99 -12
- package/skills/gmt-basics/SKILL.md +57 -15
- package/skills/gmt-integration/SKILL.md +24 -9
- package/skills/gmt-timezone/SKILL.md +134 -29
- package/dist/internal/unixZonedDateTime.d.ts +0 -22
- package/dist/internal/unixZonedDateTime.js +0 -32
- package/dist/internal/utcZonedDateTime.d.ts +0 -19
- package/dist/internal/utcZonedDateTime.js +0 -31
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseDutyLog } from "../../internal/dutyLog.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate whether a value is a duty log every `duty/` function accepts.
|
|
4
|
+
*
|
|
5
|
+
* - True for an array of `{ status, start, end }` entries where `status` is a string and `start`
|
|
6
|
+
* and `end` are ISO 8601 instant strings (offset required, no leap second), `end` after `start`.
|
|
7
|
+
* - Entries must be ordered by `start` and must not overlap. One may start exactly where the
|
|
8
|
+
* previous one ends, since entries are half-open, or later, leaving a gap. Order is by instant,
|
|
9
|
+
* not text.
|
|
10
|
+
* - `[]` is a valid, empty log. Extra keys on an entry are ignored.
|
|
11
|
+
* - Every other `duty/` function returns its sentinel for a log this rejects.
|
|
12
|
+
* - Returns `false` for a non-array, an entry that is not an object, a non-string status, a bound
|
|
13
|
+
* that is not an instant, a zero-length or inverted entry, and entries out of order or
|
|
14
|
+
* overlapping.
|
|
15
|
+
*
|
|
16
|
+
* @param log candidate array of `{ status, start, end }` records
|
|
17
|
+
* @returns boolean indicating whether the log is valid
|
|
18
|
+
*
|
|
19
|
+
* @example isValidDutyLog([{ status: "off", start: "2024-01-01T00:00:00Z", end: "2024-01-01T10:00:00Z" }, { status: "driving", start: "2024-01-01T10:00:00Z", end: "2024-01-01T15:00:00Z" }]) // true
|
|
20
|
+
* @example isValidDutyLog([]) // true — an empty log
|
|
21
|
+
* @example isValidDutyLog([{ status: "on", start: "2024-01-01T02:00:00Z", end: "2024-01-01T01:00:00Z" }]) // false — inverted
|
|
22
|
+
* @example isValidDutyLog([{ status: "on", start: "2024-01-01T00:00:00Z", end: "2024-01-01T02:00:00Z" }, { status: "off", start: "2024-01-01T01:59:59Z", end: "2024-01-01T03:00:00Z" }]) // false — overlapping
|
|
23
|
+
* @example isValidDutyLog([{ status: "on", start: "2024-01-01T00:00:00", end: "2024-01-01T01:00:00Z" }]) // false — no offset
|
|
24
|
+
*/
|
|
25
|
+
export function isValidDutyLog(log) {
|
|
26
|
+
try {
|
|
27
|
+
return parseDutyLog(log) !== null;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Never throws (Core Rule 3): a hostile
|
|
31
|
+
// argument is invalid input, not an exception.
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "@js-temporal/polyfill";
|
|
2
2
|
export * from "./calendar/index.js";
|
|
3
3
|
export * from "./duration/index.js";
|
|
4
|
+
export * from "./duty/index.js";
|
|
4
5
|
export * from "./instant/index.js";
|
|
5
6
|
export * from "./intermodal/index.js";
|
|
6
7
|
export * from "./interval/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "@js-temporal/polyfill";
|
|
2
2
|
export * from "./calendar/index.js";
|
|
3
3
|
export * from "./duration/index.js";
|
|
4
|
+
export * from "./duty/index.js";
|
|
4
5
|
export * from "./instant/index.js";
|
|
5
6
|
export * from "./intermodal/index.js";
|
|
6
7
|
export * from "./interval/index.js";
|
|
@@ -32,9 +32,12 @@ export type LocalTimeClassification = "unique" | "ambiguous" | "nonexistent";
|
|
|
32
32
|
* annotations are read as `Temporal.PlainDateTime.from` reads them, so a time zone annotation
|
|
33
33
|
* is ignored and `timeZone` alone is the zone.
|
|
34
34
|
* - Returns null on invalid input — never `"unique"`, which would read as a verdict.
|
|
35
|
+
* - `timeZone` may be a UTC offset, including one `getTimeZoneOffset` returned with seconds. A
|
|
36
|
+
* fixed offset names one instant for every wall time, so the classification is always `"unique"`.
|
|
35
37
|
*
|
|
36
38
|
* @param localDateTime zoneless ISO 8601 local datetime string (e.g. "2024-11-03T01:30:00")
|
|
37
|
-
* @param timeZone IANA name or UTC offset the wall time is read in
|
|
39
|
+
* @param timeZone IANA name or UTC offset the wall time is read in: a time zone identifier
|
|
40
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
38
41
|
* @returns "unique" | "ambiguous" | "nonexistent", or null on invalid input
|
|
39
42
|
*
|
|
40
43
|
* @example classifyLocal("2024-07-15T12:00:00", "America/New_York") // "unique"
|
|
@@ -44,6 +47,7 @@ export type LocalTimeClassification = "unique" | "ambiguous" | "nonexistent";
|
|
|
44
47
|
* @example classifyLocal("2024-09-29T03:15:00", "Pacific/Chatham") // "nonexistent" (a 45-minute-offset zone's gap)
|
|
45
48
|
* @example classifyLocal("2011-12-30T12:00:00", "Pacific/Apia") // "nonexistent" (the day Samoa skipped crossing the date line)
|
|
46
49
|
* @example classifyLocal("2024-11-03T01:30:00", "UTC") // "unique" (UTC has no transitions)
|
|
50
|
+
* @example classifyLocal("1970-01-01T12:00:00", "-00:44:30") // "unique" (a fixed offset has no transitions)
|
|
47
51
|
* @example classifyLocal("2024-11-03T01:30:00-04:00", "America/New_York") // null (not a zoneless wall time)
|
|
48
52
|
* @example classifyLocal("2024-11-03T01:30:00", "Invalid/Zone") // null
|
|
49
53
|
*/
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { isValidDateTime } from "../../plain/validate/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import { plainToZoned } from "../../internal/index.js";
|
|
3
|
+
import { instantOfWallClock, isoStringBody, plainToZoned, zoneFrame, } from "../../internal/index.js";
|
|
5
4
|
/**
|
|
6
5
|
* Report whether a zoneless local wall time is unique, ambiguous or nonexistent in a zone —
|
|
7
6
|
* before any policy resolves it.
|
|
@@ -20,9 +19,12 @@ import { plainToZoned } from "../../internal/index.js";
|
|
|
20
19
|
* annotations are read as `Temporal.PlainDateTime.from` reads them, so a time zone annotation
|
|
21
20
|
* is ignored and `timeZone` alone is the zone.
|
|
22
21
|
* - Returns null on invalid input — never `"unique"`, which would read as a verdict.
|
|
22
|
+
* - `timeZone` may be a UTC offset, including one `getTimeZoneOffset` returned with seconds. A
|
|
23
|
+
* fixed offset names one instant for every wall time, so the classification is always `"unique"`.
|
|
23
24
|
*
|
|
24
25
|
* @param localDateTime zoneless ISO 8601 local datetime string (e.g. "2024-11-03T01:30:00")
|
|
25
|
-
* @param timeZone IANA name or UTC offset the wall time is read in
|
|
26
|
+
* @param timeZone IANA name or UTC offset the wall time is read in: a time zone identifier
|
|
27
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
26
28
|
* @returns "unique" | "ambiguous" | "nonexistent", or null on invalid input
|
|
27
29
|
*
|
|
28
30
|
* @example classifyLocal("2024-07-15T12:00:00", "America/New_York") // "unique"
|
|
@@ -32,17 +34,25 @@ import { plainToZoned } from "../../internal/index.js";
|
|
|
32
34
|
* @example classifyLocal("2024-09-29T03:15:00", "Pacific/Chatham") // "nonexistent" (a 45-minute-offset zone's gap)
|
|
33
35
|
* @example classifyLocal("2011-12-30T12:00:00", "Pacific/Apia") // "nonexistent" (the day Samoa skipped crossing the date line)
|
|
34
36
|
* @example classifyLocal("2024-11-03T01:30:00", "UTC") // "unique" (UTC has no transitions)
|
|
37
|
+
* @example classifyLocal("1970-01-01T12:00:00", "-00:44:30") // "unique" (a fixed offset has no transitions)
|
|
35
38
|
* @example classifyLocal("2024-11-03T01:30:00-04:00", "America/New_York") // null (not a zoneless wall time)
|
|
36
39
|
* @example classifyLocal("2024-11-03T01:30:00", "Invalid/Zone") // null
|
|
37
40
|
*/
|
|
38
41
|
export function classifyLocal(localDateTime, timeZone) {
|
|
39
|
-
|
|
42
|
+
const frame = zoneFrame(timeZone);
|
|
43
|
+
if (!isValidDateTime(localDateTime) || frame === null) {
|
|
40
44
|
return null;
|
|
41
45
|
}
|
|
42
46
|
try {
|
|
47
|
+
// A fixed offset has no transition: a wall time it can place is one instant, and one it
|
|
48
|
+
// cannot (past the instant range) throws.
|
|
49
|
+
if (frame.shiftNanoseconds !== 0n) {
|
|
50
|
+
instantOfWallClock(isoStringBody(localDateTime), frame);
|
|
51
|
+
return "unique";
|
|
52
|
+
}
|
|
43
53
|
const wallClock = Temporal.PlainDateTime.from(localDateTime);
|
|
44
|
-
const earliest = plainToZoned(wallClock, timeZone, "earlier");
|
|
45
|
-
const latest = plainToZoned(wallClock, timeZone, "later");
|
|
54
|
+
const earliest = plainToZoned(wallClock, frame.timeZone, "earlier");
|
|
55
|
+
const latest = plainToZoned(wallClock, frame.timeZone, "later");
|
|
46
56
|
if (earliest.epochNanoseconds === latest.epochNanoseconds) {
|
|
47
57
|
return "unique";
|
|
48
58
|
}
|
|
@@ -29,6 +29,10 @@ import type { OffsetInstant } from "./toOffsetInstant.js";
|
|
|
29
29
|
* string whose local date is −271821-04-19 is refused by `toOffsetInstant`. Without a `timeZone` there is no zone to resolve against, so the
|
|
30
30
|
* full `±HH:MM:SS` is written instead; that is ISO 8601, not RFC 9557.
|
|
31
31
|
* - Returns `""` on invalid input.
|
|
32
|
+
* - A `timeZone` that is an offset with seconds (`-00:44:30`) returns `""`, as any offset there
|
|
33
|
+
* does. A written zone cannot carry seconds (RFC 9557 §4.1), so the result could not name it.
|
|
34
|
+
* Pass the IANA name as `timeZone`, or leave `timeZone` out for the local time with its full
|
|
35
|
+
* offset and no bracket.
|
|
32
36
|
*
|
|
33
37
|
* @param value `{ instant, offset, timeZone? }` pair, as produced by `toOffsetInstant`
|
|
34
38
|
* @returns local ISO 8601 string carrying the pair's own offset, or "" on invalid input
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
2
|
import { formatUtcOffset, parseInstantNanoseconds, parseUtcOffsetNanoseconds, wallClockAtOffset, } from "../../internal/index.js";
|
|
3
3
|
import { utcOffset } from "../../regex/index.js";
|
|
4
|
+
import { isObject } from "../../internal/isObject.js";
|
|
4
5
|
/**
|
|
5
6
|
* Render an instant-plus-offset pair back to the local time it describes.
|
|
6
7
|
*
|
|
@@ -31,6 +32,10 @@ import { utcOffset } from "../../regex/index.js";
|
|
|
31
32
|
* string whose local date is −271821-04-19 is refused by `toOffsetInstant`. Without a `timeZone` there is no zone to resolve against, so the
|
|
32
33
|
* full `±HH:MM:SS` is written instead; that is ISO 8601, not RFC 9557.
|
|
33
34
|
* - Returns `""` on invalid input.
|
|
35
|
+
* - A `timeZone` that is an offset with seconds (`-00:44:30`) returns `""`, as any offset there
|
|
36
|
+
* does. A written zone cannot carry seconds (RFC 9557 §4.1), so the result could not name it.
|
|
37
|
+
* Pass the IANA name as `timeZone`, or leave `timeZone` out for the local time with its full
|
|
38
|
+
* offset and no bracket.
|
|
34
39
|
*
|
|
35
40
|
* @param value `{ instant, offset, timeZone? }` pair, as produced by `toOffsetInstant`
|
|
36
41
|
* @returns local ISO 8601 string carrying the pair's own offset, or "" on invalid input
|
|
@@ -50,7 +55,7 @@ import { utcOffset } from "../../regex/index.js";
|
|
|
50
55
|
*/
|
|
51
56
|
export function fromOffsetInstant(value) {
|
|
52
57
|
try {
|
|
53
|
-
if (
|
|
58
|
+
if (!isObject(value)) {
|
|
54
59
|
return "";
|
|
55
60
|
}
|
|
56
61
|
const epochNanoseconds = parseInstantNanoseconds(value.instant);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Disambiguation } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
|
-
* Resolve a zoneless local wall time
|
|
3
|
+
* Resolve a zoneless local wall time in a time zone and return the instant it names.
|
|
4
4
|
*
|
|
5
5
|
* Feeds deliver wall times with no offset all the time — "gate-out 08:00" — and turning one
|
|
6
6
|
* into an instant takes a zone the sender did not send plus a policy for the two days a year
|
|
@@ -16,9 +16,13 @@ import type { Disambiguation } from "../../types/index.js";
|
|
|
16
16
|
* are read as `Temporal.PlainDateTime.from` reads them, so a time zone annotation
|
|
17
17
|
* (`[America/New_York]`) is ignored and `timeZone` alone resolves the wall time.
|
|
18
18
|
* - Returns `""` on invalid input.
|
|
19
|
+
* - `timeZone` may be a UTC offset, including one `getTimeZoneOffset` returned with seconds. A
|
|
20
|
+
* fixed offset names one instant for every wall time, so `disambiguation` has nothing to decide
|
|
21
|
+
* and `"reject"` does not reject.
|
|
19
22
|
*
|
|
20
23
|
* @param localDateTime zoneless ISO 8601 local datetime string (e.g. "2024-11-03T01:30:00")
|
|
21
|
-
* @param timeZone IANA name or UTC offset the wall time is read in
|
|
24
|
+
* @param timeZone IANA name or UTC offset the wall time is read in: a time zone identifier
|
|
25
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
22
26
|
* @param optionsArg How an ambiguous or nonexistent wall time is resolved
|
|
23
27
|
* @returns UTC instant string ending in "Z", or "" on invalid input
|
|
24
28
|
*
|
|
@@ -29,6 +33,7 @@ import type { Disambiguation } from "../../types/index.js";
|
|
|
29
33
|
* @example resolveLocal("2024-03-10T02:30:00", "America/New_York") // "2024-03-10T07:30:00Z" (nonexistent; "compatible" takes the later)
|
|
30
34
|
* @example resolveLocal("2024-03-10T02:30:00", "America/New_York", { disambiguation: "earlier" }) // "2024-03-10T06:30:00Z"
|
|
31
35
|
* @example resolveLocal("2024-07-15T12:00:00-04:00", "America/New_York") // "" (not a zoneless wall time)
|
|
36
|
+
* @example resolveLocal("1970-01-01T12:00:00", "-00:44:30") // "1970-01-01T12:44:30Z" (a stored offset with seconds, what `getTimeZoneOffset` returns for Africa/Monrovia then)
|
|
32
37
|
* @example resolveLocal("2024-07-15T12:00:00[foo=bar]", "America/New_York") // "2024-07-15T16:00:00Z" (elective annotation ignored)
|
|
33
38
|
* @example resolveLocal("2024-07-15T12:00:00", "Invalid/Zone") // ""
|
|
34
39
|
*/
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isValidDateTime } from "../../plain/validate/index.js";
|
|
2
|
-
import {
|
|
3
|
-
import { isoStringBody, zonedDateTimeFrom } from "../../internal/index.js";
|
|
2
|
+
import { instantOfWallClock, isoStringBody, zonedDateTimeFrom, zoneFrame, } from "../../internal/index.js";
|
|
4
3
|
import { isOptionsArgument } from "../../internal/isObject.js";
|
|
5
4
|
import { optionOrDefault } from "../../internal/optionOrDefault.js";
|
|
6
5
|
const DISAMBIGUATIONS = [
|
|
@@ -10,7 +9,7 @@ const DISAMBIGUATIONS = [
|
|
|
10
9
|
"reject",
|
|
11
10
|
];
|
|
12
11
|
/**
|
|
13
|
-
* Resolve a zoneless local wall time
|
|
12
|
+
* Resolve a zoneless local wall time in a time zone and return the instant it names.
|
|
14
13
|
*
|
|
15
14
|
* Feeds deliver wall times with no offset all the time — "gate-out 08:00" — and turning one
|
|
16
15
|
* into an instant takes a zone the sender did not send plus a policy for the two days a year
|
|
@@ -26,9 +25,13 @@ const DISAMBIGUATIONS = [
|
|
|
26
25
|
* are read as `Temporal.PlainDateTime.from` reads them, so a time zone annotation
|
|
27
26
|
* (`[America/New_York]`) is ignored and `timeZone` alone resolves the wall time.
|
|
28
27
|
* - Returns `""` on invalid input.
|
|
28
|
+
* - `timeZone` may be a UTC offset, including one `getTimeZoneOffset` returned with seconds. A
|
|
29
|
+
* fixed offset names one instant for every wall time, so `disambiguation` has nothing to decide
|
|
30
|
+
* and `"reject"` does not reject.
|
|
29
31
|
*
|
|
30
32
|
* @param localDateTime zoneless ISO 8601 local datetime string (e.g. "2024-11-03T01:30:00")
|
|
31
|
-
* @param timeZone IANA name or UTC offset the wall time is read in
|
|
33
|
+
* @param timeZone IANA name or UTC offset the wall time is read in: a time zone identifier
|
|
34
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
32
35
|
* @param optionsArg How an ambiguous or nonexistent wall time is resolved
|
|
33
36
|
* @returns UTC instant string ending in "Z", or "" on invalid input
|
|
34
37
|
*
|
|
@@ -39,6 +42,7 @@ const DISAMBIGUATIONS = [
|
|
|
39
42
|
* @example resolveLocal("2024-03-10T02:30:00", "America/New_York") // "2024-03-10T07:30:00Z" (nonexistent; "compatible" takes the later)
|
|
40
43
|
* @example resolveLocal("2024-03-10T02:30:00", "America/New_York", { disambiguation: "earlier" }) // "2024-03-10T06:30:00Z"
|
|
41
44
|
* @example resolveLocal("2024-07-15T12:00:00-04:00", "America/New_York") // "" (not a zoneless wall time)
|
|
45
|
+
* @example resolveLocal("1970-01-01T12:00:00", "-00:44:30") // "1970-01-01T12:44:30Z" (a stored offset with seconds, what `getTimeZoneOffset` returns for Africa/Monrovia then)
|
|
42
46
|
* @example resolveLocal("2024-07-15T12:00:00[foo=bar]", "America/New_York") // "2024-07-15T16:00:00Z" (elective annotation ignored)
|
|
43
47
|
* @example resolveLocal("2024-07-15T12:00:00", "Invalid/Zone") // ""
|
|
44
48
|
*/
|
|
@@ -48,15 +52,19 @@ export function resolveLocal(localDateTime, timeZone, optionsArg) {
|
|
|
48
52
|
return "";
|
|
49
53
|
}
|
|
50
54
|
const disambiguation = optionOrDefault(optionsArg?.disambiguation, "compatible");
|
|
55
|
+
const frame = zoneFrame(timeZone);
|
|
51
56
|
if (!isValidDateTime(localDateTime) ||
|
|
52
|
-
|
|
57
|
+
frame === null ||
|
|
53
58
|
!DISAMBIGUATIONS.includes(disambiguation)) {
|
|
54
59
|
return "";
|
|
55
60
|
}
|
|
56
61
|
try {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
// An offset with seconds is no time zone identifier, so it cannot go in a bracket. It needs
|
|
63
|
+
// none: the wall time at a fixed offset is one instant, whatever `disambiguation` says.
|
|
64
|
+
if (frame.shiftNanoseconds !== 0n) {
|
|
65
|
+
return instantOfWallClock(isoStringBody(localDateTime), frame).toString();
|
|
66
|
+
}
|
|
67
|
+
return zonedDateTimeFrom(`${isoStringBody(localDateTime)}[${frame.timeZone}]`, { disambiguation })
|
|
60
68
|
.toInstant()
|
|
61
69
|
.toString();
|
|
62
70
|
}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Neither `instant` nor `offset` derives from the other, which is why both are stored. It is
|
|
5
5
|
* the shape GS1 EPCIS 2.0 (`eventTime` + a required `eventTimeZoneOffset`), UN/EDIFACT DTM
|
|
6
|
-
* (
|
|
6
|
+
* (format codes `205` and `208`, a date and time with a `±HHMM` offset) and DICOM (`DT` +
|
|
7
|
+
* `&ZZXX`) all exchange.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* import { OffsetInstant } from "@northguild/gmt/instant";
|
|
@@ -52,12 +53,13 @@ export interface OffsetInstant {
|
|
|
52
53
|
* event happened when all it has is the offset it already stores. Every other bracketed
|
|
53
54
|
* identifier Temporal accepts is kept, including the single-component IANA names (`EST5EDT`,
|
|
54
55
|
* `Zulu`), in its IANA casing.
|
|
55
|
-
* - `timeZone` names the zone the offset is read in, and is how a UTC-only feed gets a pair
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* `
|
|
59
|
-
* (
|
|
60
|
-
*
|
|
56
|
+
* - `timeZone` names the zone the offset is read in, and is how a UTC-only feed gets a pair with a
|
|
57
|
+
* local offset. It also overrides a zone bracketed in the string — the instant is unchanged
|
|
58
|
+
* either way, only the local rendering differs. Any IANA Zone or Link name is accepted,
|
|
59
|
+
* single-component ones (`Japan`, `Zulu`, `EST5EDT`) included, and so is a UTC offset: a time
|
|
60
|
+
* zone identifier (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what
|
|
61
|
+
* `getTimeZoneOffset` returns). An offset (`"-05:00"`, `"-00:44:30"`) sets the pair's offset and,
|
|
62
|
+
* like a bracketed offset zone, yields no `timeZone` field.
|
|
61
63
|
* - The returned `timeZone` is the identifier in its IANA casing on every path —
|
|
62
64
|
* `"america/new_york"` comes back as `"America/New_York"` — because identifiers match
|
|
63
65
|
* case-insensitively (ECMA-402). That is what the bracket path and `fromOffsetInstant` return,
|
|
@@ -82,7 +84,8 @@ export interface OffsetInstant {
|
|
|
82
84
|
* - Returns null on invalid input, not a zero-offset pair — `+00:00` is a real offset.
|
|
83
85
|
*
|
|
84
86
|
* @param value ISO 8601 instant string, with an offset designator and optionally a bracketed zone
|
|
85
|
-
* @param timeZone optional IANA name or UTC offset to read the offset in
|
|
87
|
+
* @param timeZone optional IANA name or UTC offset to read the offset in: a time zone identifier
|
|
88
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
86
89
|
* @returns `{ instant, offset, timeZone? }`, or null on invalid input
|
|
87
90
|
*
|
|
88
91
|
* @example toOffsetInstant("2024-07-15T12:00:00-04:00[America/New_York]") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00", timeZone: "America/New_York" }
|
|
@@ -91,6 +94,7 @@ export interface OffsetInstant {
|
|
|
91
94
|
* @example toOffsetInstant("2024-07-15T16:00:00Z", "America/New_York") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00", timeZone: "America/New_York" }
|
|
92
95
|
* @example toOffsetInstant("2024-01-15T17:00:00Z", "America/New_York") // { instant: "2024-01-15T17:00:00Z", offset: "-05:00", timeZone: "America/New_York" } — same wall time, different offset, six months apart
|
|
93
96
|
* @example toOffsetInstant("1970-01-01T00:00:00Z", "Africa/Monrovia") // { instant: "1970-01-01T00:00:00Z", offset: "-00:44:30", timeZone: "Africa/Monrovia" }
|
|
97
|
+
* @example toOffsetInstant("1970-01-01T12:44:30Z", "-00:44:30") // { instant: "1970-01-01T12:44:30Z", offset: "-00:44:30" } — a stored offset with seconds, and no timeZone field
|
|
94
98
|
* @example toOffsetInstant("1969-12-31T23:15:30-00:45[Africa/Monrovia]") // { instant: "1970-01-01T00:00:00Z", offset: "-00:44:30", timeZone: "Africa/Monrovia" } — the zone, not the rounded offset, fixes the instant
|
|
95
99
|
* @example toOffsetInstant("2024-07-15T12:00:00-04:00[-04:00]") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00" } — a bracketed offset is not a zone, so no timeZone field
|
|
96
100
|
* @example toOffsetInstant("2024-07-15T12:00:00-05:00[America/New_York]") // null (offset contradicts the bracketed zone)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
-
import { formatUtcOffset, isoStringBody, parseInstantNanoseconds, TIME_ZONE_ANNOTATION, zonedDateTimeFrom, } from "../../internal/index.js";
|
|
2
|
+
import { formatUtcOffset, frameOffset, isoStringBody, parseInstantNanoseconds, TIME_ZONE_ANNOTATION, zonedDateTimeFrom, zoneFrame, } from "../../internal/index.js";
|
|
3
3
|
import { utcOffset } from "../../regex/index.js";
|
|
4
|
-
import { isValidTimeZone } from "../../zoned/validate/index.js";
|
|
5
4
|
/** A leading RFC 9557 time zone annotation: `[zone]` or `[!zone]`, with no `=`. */
|
|
6
5
|
const timeZoneAnnotation = new RegExp(`^${TIME_ZONE_ANNOTATION}`);
|
|
7
6
|
/**
|
|
@@ -24,12 +23,13 @@ const timeZoneAnnotation = new RegExp(`^${TIME_ZONE_ANNOTATION}`);
|
|
|
24
23
|
* event happened when all it has is the offset it already stores. Every other bracketed
|
|
25
24
|
* identifier Temporal accepts is kept, including the single-component IANA names (`EST5EDT`,
|
|
26
25
|
* `Zulu`), in its IANA casing.
|
|
27
|
-
* - `timeZone` names the zone the offset is read in, and is how a UTC-only feed gets a pair
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* `
|
|
31
|
-
* (
|
|
32
|
-
*
|
|
26
|
+
* - `timeZone` names the zone the offset is read in, and is how a UTC-only feed gets a pair with a
|
|
27
|
+
* local offset. It also overrides a zone bracketed in the string — the instant is unchanged
|
|
28
|
+
* either way, only the local rendering differs. Any IANA Zone or Link name is accepted,
|
|
29
|
+
* single-component ones (`Japan`, `Zulu`, `EST5EDT`) included, and so is a UTC offset: a time
|
|
30
|
+
* zone identifier (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what
|
|
31
|
+
* `getTimeZoneOffset` returns). An offset (`"-05:00"`, `"-00:44:30"`) sets the pair's offset and,
|
|
32
|
+
* like a bracketed offset zone, yields no `timeZone` field.
|
|
33
33
|
* - The returned `timeZone` is the identifier in its IANA casing on every path —
|
|
34
34
|
* `"america/new_york"` comes back as `"America/New_York"` — because identifiers match
|
|
35
35
|
* case-insensitively (ECMA-402). That is what the bracket path and `fromOffsetInstant` return,
|
|
@@ -54,7 +54,8 @@ const timeZoneAnnotation = new RegExp(`^${TIME_ZONE_ANNOTATION}`);
|
|
|
54
54
|
* - Returns null on invalid input, not a zero-offset pair — `+00:00` is a real offset.
|
|
55
55
|
*
|
|
56
56
|
* @param value ISO 8601 instant string, with an offset designator and optionally a bracketed zone
|
|
57
|
-
* @param timeZone optional IANA name or UTC offset to read the offset in
|
|
57
|
+
* @param timeZone optional IANA name or UTC offset to read the offset in: a time zone identifier
|
|
58
|
+
* (`+05:30`, `+0530`, `-08`) or a stored offset (`±HH:MM[:SS]`, what `getTimeZoneOffset` returns)
|
|
58
59
|
* @returns `{ instant, offset, timeZone? }`, or null on invalid input
|
|
59
60
|
*
|
|
60
61
|
* @example toOffsetInstant("2024-07-15T12:00:00-04:00[America/New_York]") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00", timeZone: "America/New_York" }
|
|
@@ -63,6 +64,7 @@ const timeZoneAnnotation = new RegExp(`^${TIME_ZONE_ANNOTATION}`);
|
|
|
63
64
|
* @example toOffsetInstant("2024-07-15T16:00:00Z", "America/New_York") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00", timeZone: "America/New_York" }
|
|
64
65
|
* @example toOffsetInstant("2024-01-15T17:00:00Z", "America/New_York") // { instant: "2024-01-15T17:00:00Z", offset: "-05:00", timeZone: "America/New_York" } — same wall time, different offset, six months apart
|
|
65
66
|
* @example toOffsetInstant("1970-01-01T00:00:00Z", "Africa/Monrovia") // { instant: "1970-01-01T00:00:00Z", offset: "-00:44:30", timeZone: "Africa/Monrovia" }
|
|
67
|
+
* @example toOffsetInstant("1970-01-01T12:44:30Z", "-00:44:30") // { instant: "1970-01-01T12:44:30Z", offset: "-00:44:30" } — a stored offset with seconds, and no timeZone field
|
|
66
68
|
* @example toOffsetInstant("1969-12-31T23:15:30-00:45[Africa/Monrovia]") // { instant: "1970-01-01T00:00:00Z", offset: "-00:44:30", timeZone: "Africa/Monrovia" } — the zone, not the rounded offset, fixes the instant
|
|
67
69
|
* @example toOffsetInstant("2024-07-15T12:00:00-04:00[-04:00]") // { instant: "2024-07-15T16:00:00Z", offset: "-04:00" } — a bracketed offset is not a zone, so no timeZone field
|
|
68
70
|
* @example toOffsetInstant("2024-07-15T12:00:00-05:00[America/New_York]") // null (offset contradicts the bracketed zone)
|
|
@@ -83,7 +85,8 @@ export function toOffsetInstant(value, timeZone) {
|
|
|
83
85
|
if (epochNanoseconds === null) {
|
|
84
86
|
return null;
|
|
85
87
|
}
|
|
86
|
-
|
|
88
|
+
const frame = timeZone === undefined ? undefined : zoneFrame(timeZone);
|
|
89
|
+
if (frame === null) {
|
|
87
90
|
return null;
|
|
88
91
|
}
|
|
89
92
|
try {
|
|
@@ -116,7 +119,12 @@ export function toOffsetInstant(value, timeZone) {
|
|
|
116
119
|
const instant = bracketed !== null
|
|
117
120
|
? bracketed.toInstant()
|
|
118
121
|
: Temporal.Instant.fromEpochNanoseconds(epochNanoseconds);
|
|
119
|
-
|
|
122
|
+
// A stored offset with seconds is the pair's offset as it stands. Like an offset identifier it
|
|
123
|
+
// names no place, so it fills no `timeZone` field.
|
|
124
|
+
if (frame !== undefined && frame.shiftNanoseconds !== 0n) {
|
|
125
|
+
return { instant: instant.toString(), offset: frameOffset(frame) };
|
|
126
|
+
}
|
|
127
|
+
const resolvedZone = frame?.timeZone ?? bracketedZone;
|
|
120
128
|
if (resolvedZone !== undefined) {
|
|
121
129
|
return offsetInstantInZone(instant, resolvedZone);
|
|
122
130
|
}
|
package/dist/instant/index.d.ts
CHANGED
package/dist/instant/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./isValidUtcOffset.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./isValidUtcOffset.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return true when `value` is a UTC offset in the form the offset-instant pair stores: ISO 8601
|
|
3
|
+
* extended `±HH:MM`, optionally `±HH:MM:SS`.
|
|
4
|
+
*
|
|
5
|
+
* - This is the offset `toOffsetInstant` returns and `fromOffsetInstant` takes, and the one
|
|
6
|
+
* `getTimeZoneOffset` and `getZonedOffset` return.
|
|
7
|
+
* - **The `utcOffset` pattern is the whole check.** Every string it matches is in range (hour
|
|
8
|
+
* `00`–`23`, minute and second `00`–`59`), so this validator is the pattern test plus the
|
|
9
|
+
* answer false for a non-string.
|
|
10
|
+
* - `Z` is false: it is a designator meaning "this string is already UTC", and for an event at
|
|
11
|
+
* UTC the pair's offset is `+00:00`.
|
|
12
|
+
* - Seconds are allowed because some zones did not run on a whole minute: `Africa/Monrovia` was
|
|
13
|
+
* `-00:44:30` until 1972. A fraction of a second is false.
|
|
14
|
+
* - Basic format (`-0400`) and an hour alone (`-04`) are false.
|
|
15
|
+
* - `-00:00` is true, and the functions that take an offset read it as `+00:00`.
|
|
16
|
+
* - A function whose result has no zone in it takes this offset in its time zone position too. A
|
|
17
|
+
* function that returns a zoned string, or formats with `Intl`, takes a time zone identifier
|
|
18
|
+
* only: check that with `isValidTimeZone`, which accepts `+0530` and `-08` and rejects an offset
|
|
19
|
+
* with seconds.
|
|
20
|
+
*
|
|
21
|
+
* @param value candidate UTC offset string
|
|
22
|
+
* @returns boolean indicating validity
|
|
23
|
+
*
|
|
24
|
+
* @example isValidUtcOffset("-04:00") // true
|
|
25
|
+
* @example isValidUtcOffset("+05:45") // true
|
|
26
|
+
* @example isValidUtcOffset("-00:44:30") // true (Africa/Monrovia before 1972)
|
|
27
|
+
* @example isValidUtcOffset("Z") // false (a designator, not an offset)
|
|
28
|
+
* @example isValidUtcOffset("-0400") // false (basic format)
|
|
29
|
+
* @example isValidUtcOffset("+24:00") // false (out of range)
|
|
30
|
+
* @example isValidUtcOffset("America/New_York") // false (a zone, not an offset)
|
|
31
|
+
*/
|
|
32
|
+
export declare function isValidUtcOffset(value: string): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { utcOffset } from "../../regex/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Return true when `value` is a UTC offset in the form the offset-instant pair stores: ISO 8601
|
|
4
|
+
* extended `±HH:MM`, optionally `±HH:MM:SS`.
|
|
5
|
+
*
|
|
6
|
+
* - This is the offset `toOffsetInstant` returns and `fromOffsetInstant` takes, and the one
|
|
7
|
+
* `getTimeZoneOffset` and `getZonedOffset` return.
|
|
8
|
+
* - **The `utcOffset` pattern is the whole check.** Every string it matches is in range (hour
|
|
9
|
+
* `00`–`23`, minute and second `00`–`59`), so this validator is the pattern test plus the
|
|
10
|
+
* answer false for a non-string.
|
|
11
|
+
* - `Z` is false: it is a designator meaning "this string is already UTC", and for an event at
|
|
12
|
+
* UTC the pair's offset is `+00:00`.
|
|
13
|
+
* - Seconds are allowed because some zones did not run on a whole minute: `Africa/Monrovia` was
|
|
14
|
+
* `-00:44:30` until 1972. A fraction of a second is false.
|
|
15
|
+
* - Basic format (`-0400`) and an hour alone (`-04`) are false.
|
|
16
|
+
* - `-00:00` is true, and the functions that take an offset read it as `+00:00`.
|
|
17
|
+
* - A function whose result has no zone in it takes this offset in its time zone position too. A
|
|
18
|
+
* function that returns a zoned string, or formats with `Intl`, takes a time zone identifier
|
|
19
|
+
* only: check that with `isValidTimeZone`, which accepts `+0530` and `-08` and rejects an offset
|
|
20
|
+
* with seconds.
|
|
21
|
+
*
|
|
22
|
+
* @param value candidate UTC offset string
|
|
23
|
+
* @returns boolean indicating validity
|
|
24
|
+
*
|
|
25
|
+
* @example isValidUtcOffset("-04:00") // true
|
|
26
|
+
* @example isValidUtcOffset("+05:45") // true
|
|
27
|
+
* @example isValidUtcOffset("-00:44:30") // true (Africa/Monrovia before 1972)
|
|
28
|
+
* @example isValidUtcOffset("Z") // false (a designator, not an offset)
|
|
29
|
+
* @example isValidUtcOffset("-0400") // false (basic format)
|
|
30
|
+
* @example isValidUtcOffset("+24:00") // false (out of range)
|
|
31
|
+
* @example isValidUtcOffset("America/New_York") // false (a zone, not an offset)
|
|
32
|
+
*/
|
|
33
|
+
export function isValidUtcOffset(value) {
|
|
34
|
+
return typeof value === "string" && utcOffset.test(value);
|
|
35
|
+
}
|
|
@@ -77,6 +77,12 @@ export type FreeTimeChargeOptions = FreeTimeOptions & {
|
|
|
77
77
|
* inverted dwell is a data error), `freeDays` is not a whole number of at least `0`, the
|
|
78
78
|
* options fail as they do for `freeTimeExpiry`, `tiers` has a hole, an unsafe integer or does not ascend, or the walk would pass
|
|
79
79
|
* 10,000 local days.
|
|
80
|
+
* - **Limit at an offset with seconds.** The instant is placed in the offset's whole-minute zone,
|
|
81
|
+
* moved by its seconds, and the moved instant must be inside Temporal's range. So within the
|
|
82
|
+
* offset's seconds (under a minute) of the last instant Temporal supports
|
|
83
|
+
* (`+275760-09-13T00:00:00Z`) for an offset east of UTC, or of the first
|
|
84
|
+
* (`-271821-04-20T00:00:00Z`) for one west, this returns `null`. An offset to the minute has no
|
|
85
|
+
* such limit.
|
|
80
86
|
*
|
|
81
87
|
* @param clockStart ISO 8601 instant string of the event that starts the clock
|
|
82
88
|
* @param clockEnd ISO 8601 instant string of the event that stops it (gate-out or empty return)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
-
import { bandsByTier, instantFrom, parseFreeDays, parseFreeTimeTerms, parseTiers, walkFreeTime, } from "../../internal/index.js";
|
|
2
|
+
import { bandsByTier, frameInstant, frameZoned, instantFrom, parseFreeDays, parseFreeTimeTerms, parseTiers, walkFreeTime, zoneFrame, } from "../../internal/index.js";
|
|
3
3
|
import { isValidInstant } from "../../precision/validate/isValidInstant.js";
|
|
4
4
|
/**
|
|
5
5
|
* Count the days a container is charged for between the start of its clock and its exit,
|
|
@@ -38,6 +38,12 @@ import { isValidInstant } from "../../precision/validate/isValidInstant.js";
|
|
|
38
38
|
* inverted dwell is a data error), `freeDays` is not a whole number of at least `0`, the
|
|
39
39
|
* options fail as they do for `freeTimeExpiry`, `tiers` has a hole, an unsafe integer or does not ascend, or the walk would pass
|
|
40
40
|
* 10,000 local days.
|
|
41
|
+
* - **Limit at an offset with seconds.** The instant is placed in the offset's whole-minute zone,
|
|
42
|
+
* moved by its seconds, and the moved instant must be inside Temporal's range. So within the
|
|
43
|
+
* offset's seconds (under a minute) of the last instant Temporal supports
|
|
44
|
+
* (`+275760-09-13T00:00:00Z`) for an offset east of UTC, or of the first
|
|
45
|
+
* (`-271821-04-20T00:00:00Z`) for one west, this returns `null`. An offset to the minute has no
|
|
46
|
+
* such limit.
|
|
41
47
|
*
|
|
42
48
|
* @param clockStart ISO 8601 instant string of the event that starts the clock
|
|
43
49
|
* @param clockEnd ISO 8601 instant string of the event that stops it (gate-out or empty return)
|
|
@@ -64,15 +70,17 @@ export function chargeableDays(clockStart, clockEnd, freeDays, options) {
|
|
|
64
70
|
const allowed = parseFreeDays(freeDays, 0);
|
|
65
71
|
// Read after the terms, so a non-object `options` is never read from.
|
|
66
72
|
const tiers = terms === null ? null : parseTiers(options.tiers);
|
|
73
|
+
const frame = terms === null ? null : zoneFrame(terms.timeZone);
|
|
67
74
|
if (!isValidInstant(clockStart) ||
|
|
68
75
|
!isValidInstant(clockEnd) ||
|
|
69
76
|
terms === null ||
|
|
77
|
+
frame === null ||
|
|
70
78
|
allowed === null ||
|
|
71
79
|
tiers === null) {
|
|
72
80
|
return null;
|
|
73
81
|
}
|
|
74
|
-
const start = instantFrom(clockStart)
|
|
75
|
-
const end = instantFrom(clockEnd)
|
|
82
|
+
const start = frameZoned(instantFrom(clockStart), frame);
|
|
83
|
+
const end = frameZoned(instantFrom(clockEnd), frame);
|
|
76
84
|
if (Temporal.ZonedDateTime.compare(start, end) > 0) {
|
|
77
85
|
return null;
|
|
78
86
|
}
|
|
@@ -83,7 +91,7 @@ export function chargeableDays(clockStart, clockEnd, freeDays, options) {
|
|
|
83
91
|
return {
|
|
84
92
|
freeDaysUsed: ledger.used,
|
|
85
93
|
chargeableDays: ledger.charged.length,
|
|
86
|
-
expiresAt: ledger.expiresAt
|
|
94
|
+
expiresAt: frameInstant(ledger.expiresAt, frame).toString(),
|
|
87
95
|
chargedDates: ledger.charged.map((day) => day.date),
|
|
88
96
|
byTier: bandsByTier(tiers, ledger.charged.length),
|
|
89
97
|
};
|
|
@@ -46,6 +46,12 @@ export interface FreeTime {
|
|
|
46
46
|
* least `1`, `options` is not an object, `basis` or `firstDay` is missing or unknown,
|
|
47
47
|
* `timeZone` is invalid, `basis` is `"working"` without a valid `BusinessCalendar`, or the walk
|
|
48
48
|
* would pass 10,000 local days.
|
|
49
|
+
* - **Limit at an offset with seconds.** The instant is placed in the offset's whole-minute zone,
|
|
50
|
+
* moved by its seconds, and the moved instant must be inside Temporal's range. So within the
|
|
51
|
+
* offset's seconds (under a minute) of the last instant Temporal supports
|
|
52
|
+
* (`+275760-09-13T00:00:00Z`) for an offset east of UTC, or of the first
|
|
53
|
+
* (`-271821-04-20T00:00:00Z`) for one west, this returns `null`. An offset to the minute has no
|
|
54
|
+
* such limit.
|
|
49
55
|
*
|
|
50
56
|
* @param clockStart ISO 8601 instant string of the event that starts the clock (discharge, availability or gate-out)
|
|
51
57
|
* @param freeDays whole number of free days the tariff allows, at least 1
|
|
@@ -63,5 +69,6 @@ export interface FreeTime {
|
|
|
63
69
|
* @example freeTimeExpiry("2024-06-14T19:00:00Z", 3, { basis: "working", timeZone: "America/New_York", firstDay: "eventDay" }) // null (a working-day count needs the terminal's calendar)
|
|
64
70
|
* @example freeTimeExpiry("2024-06-14T19:00:00Z", 0, { basis: "calendar", timeZone: "America/New_York", firstDay: "eventDay" }) // null (no free days means no last free day)
|
|
65
71
|
* @example freeTimeExpiry("2024-06-14T19:00:00", 3, { basis: "calendar", timeZone: "America/New_York", firstDay: "eventDay" }) // null (no offset: not an instant)
|
|
72
|
+
* @example freeTimeExpiry("1970-01-01T00:30:00Z", 3, { basis: "calendar", firstDay: "eventDay", timeZone: "-00:44:30" }) // { freeTimeStart: "1969-12-31", lastFreeDay: "1970-01-02", expiresAt: "1970-01-03T00:44:30Z" }
|
|
66
73
|
*/
|
|
67
74
|
export declare function freeTimeExpiry(clockStart: string, freeDays: number, options: FreeTimeOptions): FreeTime | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { instantFrom, parseFreeDays, parseFreeTimeTerms, walkFreeTime, } from "../../internal/index.js";
|
|
1
|
+
import { frameInstant, frameZoned, instantFrom, parseFreeDays, parseFreeTimeTerms, walkFreeTime, zoneFrame, } from "../../internal/index.js";
|
|
2
2
|
import { isValidInstant } from "../../precision/validate/isValidInstant.js";
|
|
3
3
|
/**
|
|
4
4
|
* Lay out a container's free time from the instant its clock started, and say when it ends.
|
|
@@ -38,6 +38,12 @@ import { isValidInstant } from "../../precision/validate/isValidInstant.js";
|
|
|
38
38
|
* least `1`, `options` is not an object, `basis` or `firstDay` is missing or unknown,
|
|
39
39
|
* `timeZone` is invalid, `basis` is `"working"` without a valid `BusinessCalendar`, or the walk
|
|
40
40
|
* would pass 10,000 local days.
|
|
41
|
+
* - **Limit at an offset with seconds.** The instant is placed in the offset's whole-minute zone,
|
|
42
|
+
* moved by its seconds, and the moved instant must be inside Temporal's range. So within the
|
|
43
|
+
* offset's seconds (under a minute) of the last instant Temporal supports
|
|
44
|
+
* (`+275760-09-13T00:00:00Z`) for an offset east of UTC, or of the first
|
|
45
|
+
* (`-271821-04-20T00:00:00Z`) for one west, this returns `null`. An offset to the minute has no
|
|
46
|
+
* such limit.
|
|
41
47
|
*
|
|
42
48
|
* @param clockStart ISO 8601 instant string of the event that starts the clock (discharge, availability or gate-out)
|
|
43
49
|
* @param freeDays whole number of free days the tariff allows, at least 1
|
|
@@ -55,15 +61,20 @@ import { isValidInstant } from "../../precision/validate/isValidInstant.js";
|
|
|
55
61
|
* @example freeTimeExpiry("2024-06-14T19:00:00Z", 3, { basis: "working", timeZone: "America/New_York", firstDay: "eventDay" }) // null (a working-day count needs the terminal's calendar)
|
|
56
62
|
* @example freeTimeExpiry("2024-06-14T19:00:00Z", 0, { basis: "calendar", timeZone: "America/New_York", firstDay: "eventDay" }) // null (no free days means no last free day)
|
|
57
63
|
* @example freeTimeExpiry("2024-06-14T19:00:00", 3, { basis: "calendar", timeZone: "America/New_York", firstDay: "eventDay" }) // null (no offset: not an instant)
|
|
64
|
+
* @example freeTimeExpiry("1970-01-01T00:30:00Z", 3, { basis: "calendar", firstDay: "eventDay", timeZone: "-00:44:30" }) // { freeTimeStart: "1969-12-31", lastFreeDay: "1970-01-02", expiresAt: "1970-01-03T00:44:30Z" }
|
|
58
65
|
*/
|
|
59
66
|
export function freeTimeExpiry(clockStart, freeDays, options) {
|
|
60
67
|
try {
|
|
61
68
|
const terms = parseFreeTimeTerms(options);
|
|
62
69
|
const allowed = parseFreeDays(freeDays, 1);
|
|
63
|
-
|
|
70
|
+
const frame = terms === null ? null : zoneFrame(terms.timeZone);
|
|
71
|
+
if (!isValidInstant(clockStart) ||
|
|
72
|
+
terms === null ||
|
|
73
|
+
frame === null ||
|
|
74
|
+
allowed === null) {
|
|
64
75
|
return null;
|
|
65
76
|
}
|
|
66
|
-
const start = instantFrom(clockStart)
|
|
77
|
+
const start = frameZoned(instantFrom(clockStart), frame);
|
|
67
78
|
const ledger = walkFreeTime(start, allowed, terms);
|
|
68
79
|
if (ledger === null) {
|
|
69
80
|
return null;
|
|
@@ -71,7 +82,7 @@ export function freeTimeExpiry(clockStart, freeDays, options) {
|
|
|
71
82
|
return {
|
|
72
83
|
freeTimeStart: ledger.free[0].date,
|
|
73
84
|
lastFreeDay: ledger.free[allowed - 1].date,
|
|
74
|
-
expiresAt: ledger.expiresAt
|
|
85
|
+
expiresAt: frameInstant(ledger.expiresAt, frame).toString(),
|
|
75
86
|
};
|
|
76
87
|
}
|
|
77
88
|
catch {
|