@@ -66,8 +66,8 @@ export const DAY_NANOS = DAY_MS * 1e6;
66
66
const MINUTE_NANOS = 60e9 ;
67
67
// Instant range is 100 million days (inclusive) before or after epoch.
68
68
const MS_MAX = DAY_MS * 1e8 ;
69
- const NS_MIN = JSBI . multiply ( DAY_NANOS_JSBI , JSBI . BigInt ( - 1e8 ) ) ;
70
- const NS_MAX = JSBI . multiply ( DAY_NANOS_JSBI , JSBI . BigInt ( 1e8 ) ) ;
69
+ const NS_MAX = epochMsToNs ( MS_MAX ) ;
70
+ const NS_MIN = JSBI . unaryMinus ( NS_MAX ) ;
71
71
// PlainDateTime range is 24 hours wider (exclusive) than the Instant range on
72
72
// both ends, to allow for valid Instant=>PlainDateTime conversion for all
73
73
// built-in time zones (whose offsets must have a magnitude less than 24 hours).
@@ -2681,13 +2681,12 @@ function GetUTCEpochMilliseconds({
2681
2681
function GetUTCEpochNanoseconds ( isoDateTime : ISODateTime ) {
2682
2682
const ms = GetUTCEpochMilliseconds ( isoDateTime ) ;
2683
2683
const subMs = isoDateTime . time . microsecond * 1e3 + isoDateTime . time . nanosecond ;
2684
- return JSBI . add ( JSBI . multiply ( JSBI . BigInt ( ms ) , MILLION ) , JSBI . BigInt ( subMs ) ) ;
2684
+ return JSBI . add ( epochMsToNs ( ms ) , JSBI . BigInt ( subMs ) ) ;
2685
2685
}
2686
2686
2687
2687
export function GetISOPartsFromEpoch ( epochNanoseconds : JSBI ) {
2688
- const { quotient, remainder } = divmod ( epochNanoseconds , MILLION ) ;
2689
- let epochMilliseconds = JSBI . toNumber ( quotient ) ;
2690
- let nanos = JSBI . toNumber ( remainder ) ;
2688
+ let epochMilliseconds = epochNsToMs ( epochNanoseconds , 'trunc' ) ;
2689
+ let nanos = JSBI . toNumber ( JSBI . remainder ( epochNanoseconds , MILLION ) ) ;
2691
2690
if ( nanos < 0 ) {
2692
2691
nanos += 1e6 ;
2693
2692
epochMilliseconds -= 1 ;
@@ -2729,7 +2728,7 @@ export function GetNamedTimeZoneNextTransition(id: string, epochNanoseconds: JSB
2729
2728
// time zone transitions don't happen in the middle of a millisecond.
2730
2729
const epochMilliseconds = epochNsToMs ( epochNanoseconds , 'floor' ) ;
2731
2730
if ( epochMilliseconds < BEFORE_FIRST_DST ) {
2732
- return GetNamedTimeZoneNextTransition ( id , JSBI . multiply ( JSBI . BigInt ( BEFORE_FIRST_DST ) , MILLION ) ) ;
2731
+ return GetNamedTimeZoneNextTransition ( id , epochMsToNs ( BEFORE_FIRST_DST ) ) ;
2733
2732
}
2734
2733
2735
2734
// Optimization: the farthest that we'll look for a next transition is 3 years
@@ -2759,7 +2758,7 @@ export function GetNamedTimeZoneNextTransition(id: string, epochNanoseconds: JSB
2759
2758
leftOffsetNs ,
2760
2759
rightOffsetNs
2761
2760
) ;
2762
- return JSBI . multiply ( JSBI . BigInt ( result ) , MILLION ) ;
2761
+ return epochMsToNs ( result ) ;
2763
2762
}
2764
2763
2765
2764
export function GetNamedTimeZonePreviousTransition ( id : string , epochNanoseconds : JSBI ) : JSBI | null {
@@ -2776,8 +2775,8 @@ export function GetNamedTimeZonePreviousTransition(id: string, epochNanoseconds:
2776
2775
const now = Date . now ( ) ;
2777
2776
const lookahead = now + DAY_MS * 366 * 3 ;
2778
2777
if ( epochMilliseconds > lookahead ) {
2779
- const prevBeforeLookahead = GetNamedTimeZonePreviousTransition ( id , JSBI . multiply ( JSBI . BigInt ( lookahead ) , MILLION ) ) ;
2780
- if ( prevBeforeLookahead === null || JSBI . lessThan ( prevBeforeLookahead , JSBI . multiply ( JSBI . BigInt ( now ) , MILLION ) ) ) {
2778
+ const prevBeforeLookahead = GetNamedTimeZonePreviousTransition ( id , epochMsToNs ( lookahead ) ) ;
2779
+ if ( prevBeforeLookahead === null || JSBI . lessThan ( prevBeforeLookahead , epochMsToNs ( now ) ) ) {
2781
2780
return prevBeforeLookahead ;
2782
2781
}
2783
2782
}
@@ -2792,7 +2791,7 @@ export function GetNamedTimeZonePreviousTransition(id: string, epochNanoseconds:
2792
2791
if ( id === 'Africa/Casablanca' || id === 'Africa/El_Aaiun' ) {
2793
2792
const lastPrecomputed = Date . UTC ( 2088 , 0 , 1 ) ; // 2088-01-01T00Z
2794
2793
if ( lastPrecomputed < epochMilliseconds ) {
2795
- return GetNamedTimeZonePreviousTransition ( id , JSBI . multiply ( JSBI . BigInt ( lastPrecomputed ) , MILLION ) ) ;
2794
+ return GetNamedTimeZonePreviousTransition ( id , epochMsToNs ( lastPrecomputed ) ) ;
2796
2795
}
2797
2796
}
2798
2797
@@ -2817,7 +2816,7 @@ export function GetNamedTimeZonePreviousTransition(id: string, epochNanoseconds:
2817
2816
leftOffsetNs ,
2818
2817
rightOffsetNs
2819
2818
) ;
2820
- return JSBI . multiply ( JSBI . BigInt ( result ) , MILLION ) ;
2819
+ return epochMsToNs ( result ) ;
2821
2820
}
2822
2821
2823
2822
// ts-prune-ignore-next TODO: remove this after tests are converted to TS
@@ -4744,8 +4743,8 @@ export function ToBigIntExternal(arg: unknown): ExternalBigInt {
4744
4743
return jsbiBI as unknown as ExternalBigInt ;
4745
4744
}
4746
4745
4747
- // rounding modes supported: floor, ceil
4748
- export function epochNsToMs ( epochNanosecondsParam : JSBI | bigint , mode : 'floor' | 'ceil' ) {
4746
+ // rounding modes supported: floor, ceil, trunc
4747
+ export function epochNsToMs ( epochNanosecondsParam : JSBI | bigint , mode : 'floor' | 'ceil' | 'trunc' ) {
4749
4748
const epochNanoseconds = ensureJSBI ( epochNanosecondsParam ) ;
4750
4749
const { quotient, remainder } = divmod ( epochNanoseconds , MILLION ) ;
4751
4750
let epochMilliseconds = JSBI . toNumber ( quotient ) ;
@@ -4754,6 +4753,11 @@ export function epochNsToMs(epochNanosecondsParam: JSBI | bigint, mode: 'floor'
4754
4753
return epochMilliseconds ;
4755
4754
}
4756
4755
4756
+ export function epochMsToNs ( epochMilliseconds : number ) {
4757
+ if ( ! Number . isInteger ( epochMilliseconds ) ) throw new RangeError ( 'epoch milliseconds must be an integer' ) ;
4758
+ return JSBI . multiply ( JSBI . BigInt ( epochMilliseconds ) , MILLION ) ;
4759
+ }
4760
+
4757
4761
export function ToBigInt ( arg : unknown ) : JSBI {
4758
4762
let prim = arg ;
4759
4763
if ( typeof arg === 'object' ) {
@@ -4789,8 +4793,9 @@ export function ToBigInt(arg: unknown): JSBI {
4789
4793
export const SystemUTCEpochNanoSeconds : ( ) => JSBI = ( ( ) => {
4790
4794
let ns = JSBI . BigInt ( Date . now ( ) % 1e6 ) ;
4791
4795
return ( ) => {
4792
- const ms = JSBI . BigInt ( Date . now ( ) ) ;
4793
- const result = JSBI . add ( JSBI . multiply ( ms , MILLION ) , ns ) ;
4796
+ const now = Date . now ( ) ;
4797
+ const ms = JSBI . BigInt ( now ) ;
4798
+ const result = JSBI . add ( epochMsToNs ( now ) , ns ) ;
4794
4799
ns = JSBI . remainder ( ms , MILLION ) ;
4795
4800
if ( JSBI . greaterThan ( result , NS_MAX ) ) return NS_MAX ;
4796
4801
if ( JSBI . lessThan ( result , NS_MIN ) ) return NS_MIN ;
0 commit comments