@@ -95,27 +95,80 @@ export function applyDuration(date: Date | number, duration: Duration): Date {
9595 return r
9696}
9797
98- export function elapsedTime ( date : Date , precision : Unit = 'second' , now = Date . now ( ) ) : Duration {
99- const delta = date . getTime ( ) - now
100- if ( delta === 0 ) return new Duration ( )
101- const sign = Math . sign ( delta )
102- const ms = Math . abs ( delta )
103- const sec = Math . floor ( ms / 1000 )
104- const min = Math . floor ( sec / 60 )
105- const hr = Math . floor ( min / 60 )
106- const day = Math . floor ( hr / 24 )
107- const month = Math . floor ( day / 30 )
108- const year = Math . floor ( month / 12 )
109- const i = unitNames . indexOf ( precision ) || unitNames . length
98+ // Calculates the elapsed time from `now` to `date`.
99+ export function elapsedTime (
100+ date : Date ,
101+ precision : Unit = 'second' ,
102+ nowTimestamp : Date | number = Date . now ( ) ,
103+ ) : Duration {
104+ const now = new Date ( nowTimestamp )
105+ // eslint-disable-next-line prefer-const
106+ let [ sign , subtrahend , minuend ] = date < now ? [ - 1 , now , date ] : [ 1 , date , now ]
107+ let ms : number
108+ let sec : number
109+ let min : number
110+ let hr : number
111+ let day : number
112+ let month : number
113+ let year : number
114+ // Using UTC to avoid timezone-specific variations.
115+ if ( subtrahend . getUTCMilliseconds ( ) >= minuend . getUTCMilliseconds ( ) ) {
116+ ms = subtrahend . getUTCMilliseconds ( ) - minuend . getUTCMilliseconds ( )
117+ } else {
118+ ms = 1000 + subtrahend . getUTCMilliseconds ( ) - minuend . getUTCMilliseconds ( )
119+ subtrahend = new Date ( subtrahend . getTime ( ) - 1000 )
120+ }
121+
122+ if ( subtrahend . getUTCSeconds ( ) >= minuend . getUTCSeconds ( ) ) {
123+ sec = subtrahend . getUTCSeconds ( ) - minuend . getUTCSeconds ( )
124+ } else {
125+ sec = 60 + subtrahend . getUTCSeconds ( ) - minuend . getUTCSeconds ( )
126+ subtrahend = new Date ( subtrahend . getTime ( ) - 1000 * 60 )
127+ }
128+
129+ if ( subtrahend . getUTCMinutes ( ) >= minuend . getUTCMinutes ( ) ) {
130+ min = subtrahend . getUTCMinutes ( ) - minuend . getUTCMinutes ( )
131+ } else {
132+ min = 60 + subtrahend . getUTCMinutes ( ) - minuend . getUTCMinutes ( )
133+ subtrahend = new Date ( subtrahend . getTime ( ) - 1000 * 60 * 60 )
134+ }
135+
136+ if ( subtrahend . getUTCHours ( ) >= minuend . getUTCHours ( ) ) {
137+ hr = subtrahend . getUTCHours ( ) - minuend . getUTCHours ( )
138+ } else {
139+ hr = 24 + subtrahend . getUTCHours ( ) - minuend . getUTCHours ( )
140+ subtrahend = new Date ( subtrahend . getTime ( ) - 1000 * 60 * 60 * 24 )
141+ }
142+
143+ if ( subtrahend . getUTCDate ( ) >= minuend . getUTCDate ( ) ) {
144+ day = subtrahend . getUTCDate ( ) - minuend . getUTCDate ( )
145+ } else {
146+ day = subtrahend . getUTCDate ( )
147+ subtrahend = new Date ( subtrahend . getTime ( ) - 1000 * 60 * 60 * 24 * day )
148+ day += Math . max ( 0 , subtrahend . getUTCDate ( ) - minuend . getUTCDate ( ) )
149+ }
150+
151+ year = subtrahend . getUTCFullYear ( ) - minuend . getUTCFullYear ( )
152+ if ( subtrahend . getUTCMonth ( ) >= minuend . getUTCMonth ( ) ) {
153+ month = subtrahend . getUTCMonth ( ) - minuend . getUTCMonth ( )
154+ } else {
155+ month = 12 + subtrahend . getUTCMonth ( ) - minuend . getUTCMonth ( )
156+ year -= 1
157+ }
158+
159+ let precisionIndex = unitNames . indexOf ( precision )
160+ if ( precisionIndex === - 1 ) {
161+ precisionIndex = unitNames . length
162+ }
110163 return new Duration (
111- i >= 0 ? year * sign : 0 ,
112- i >= 1 ? ( month - year * 12 ) * sign : 0 ,
164+ precisionIndex >= 0 ? year * sign : 0 ,
165+ precisionIndex >= 1 ? month * sign : 0 ,
113166 0 ,
114- i >= 3 ? ( day - month * 30 ) * sign : 0 ,
115- i >= 4 ? ( hr - day * 24 ) * sign : 0 ,
116- i >= 5 ? ( min - hr * 60 ) * sign : 0 ,
117- i >= 6 ? ( sec - min * 60 ) * sign : 0 ,
118- i >= 7 ? ( ms - sec * 1000 ) * sign : 0 ,
167+ precisionIndex >= 3 ? day * sign : 0 ,
168+ precisionIndex >= 4 ? hr * sign : 0 ,
169+ precisionIndex >= 5 ? min * sign : 0 ,
170+ precisionIndex >= 6 ? sec * sign : 0 ,
171+ precisionIndex >= 7 ? ms * sign : 0 ,
119172 )
120173}
121174
0 commit comments