@naturalcycles/js-lib 14.91.0 → 14.92.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,5 +1,7 @@
1
1
  import { _assert } from '../error/assert'
2
- import { IsoDateTime, UnixTimestamp } from '../types'
2
+ import { _ms } from '../time/time.util'
3
+ import { IsoDate, IsoDateTime, UnixTimestamp } from '../types'
4
+ import { LocalDate } from './localDate'
3
5
 
4
6
  export type LocalTimeUnit = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second'
5
7
 
@@ -29,7 +31,7 @@ export interface LocalTimeComponents {
29
31
  * @experimental
30
32
  */
31
33
  export class LocalTime {
32
- private constructor(private $date: Date) {}
34
+ private constructor(private $date: Date, public utcMode: boolean) {}
33
35
 
34
36
  /**
35
37
  * Parses input String into LocalDate.
@@ -45,6 +47,16 @@ export class LocalTime {
45
47
  return t
46
48
  }
47
49
 
50
+ utc(): this {
51
+ this.utcMode = true
52
+ return this
53
+ }
54
+
55
+ local(): this {
56
+ this.utcMode = false
57
+ return this
58
+ }
59
+
48
60
  /**
49
61
  * Returns null if invalid
50
62
  */
@@ -67,63 +79,65 @@ export class LocalTime {
67
79
  return null
68
80
  }
69
81
 
70
- return new LocalTime(date)
82
+ // if (utc) {
83
+ // date.setMinutes(date.getMinutes() + date.getTimezoneOffset())
84
+ // }
85
+
86
+ return new LocalTime(date, false)
71
87
  }
72
88
 
73
89
  static isValid(d: LocalTimeConfig): boolean {
74
90
  return this.parseOrNull(d) !== null
75
91
  }
76
92
 
77
- static unix(ts: UnixTimestamp): LocalTime {
78
- return new LocalTime(new Date(ts * 1000))
79
- }
80
-
81
93
  static now(): LocalTime {
82
- return this.of(new Date())
94
+ return new LocalTime(new Date(), false)
83
95
  }
84
96
 
85
97
  static fromComponents(
86
98
  c: { year: number; month: number } & Partial<LocalTimeComponents>,
87
99
  ): LocalTime {
88
- return new LocalTime(new Date(c.year, c.month - 1, c.day, c.hour, c.minute, c.second))
100
+ return new LocalTime(new Date(c.year, c.month - 1, c.day, c.hour, c.minute, c.second), false)
89
101
  }
90
102
 
91
103
  get(unit: LocalTimeUnit): number {
92
104
  if (unit === 'year') {
93
- return this.$date.getFullYear()
105
+ return this.utcMode ? this.$date.getUTCFullYear() : this.$date.getFullYear()
94
106
  }
95
107
  if (unit === 'month') {
96
- return this.$date.getMonth() + 1
108
+ return (this.utcMode ? this.$date.getUTCMonth() : this.$date.getMonth()) + 1
97
109
  }
98
110
  if (unit === 'day') {
99
- return this.$date.getDate()
111
+ return this.utcMode ? this.$date.getUTCDate() : this.$date.getDate()
100
112
  }
101
113
  if (unit === 'hour') {
102
- return this.$date.getHours()
114
+ return this.utcMode ? this.$date.getUTCHours() : this.$date.getHours()
103
115
  }
104
116
  if (unit === 'minute') {
105
- return this.$date.getMinutes()
117
+ return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes()
106
118
  }
107
119
  // second
108
- return this.$date.getSeconds()
120
+ return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds()
109
121
  }
110
122
 
111
123
  set(unit: LocalTimeUnit, v: number, mutate = false): LocalTime {
112
124
  const t = mutate ? this : this.clone()
113
125
 
126
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
114
127
  if (unit === 'year') {
115
- t.$date.setFullYear(v)
128
+ this.utcMode ? t.$date.setUTCFullYear(v) : t.$date.setFullYear(v)
116
129
  } else if (unit === 'month') {
117
- t.$date.setMonth(v - 1)
130
+ this.utcMode ? t.$date.setUTCMonth(v - 1) : t.$date.setMonth(v - 1)
118
131
  } else if (unit === 'day') {
119
- t.$date.setDate(v)
132
+ this.utcMode ? t.$date.setUTCDate(v) : t.$date.setDate(v)
120
133
  } else if (unit === 'hour') {
121
- t.$date.setHours(v)
134
+ this.utcMode ? t.$date.setUTCHours(v) : t.$date.setHours(v)
122
135
  } else if (unit === 'minute') {
123
- t.$date.setMinutes(v)
136
+ this.utcMode ? t.$date.setUTCMinutes(v) : t.$date.setMinutes(v)
124
137
  } else if (unit === 'second') {
125
- t.$date.setSeconds(v)
138
+ this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v)
126
139
  }
140
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
127
141
 
128
142
  return t
129
143
  }
@@ -131,57 +145,59 @@ export class LocalTime {
131
145
  year(): number
132
146
  year(v: number): LocalTime
133
147
  year(v?: number): number | LocalTime {
134
- return v === undefined ? this.$date.getFullYear() : this.set('year', v)
148
+ return v === undefined ? this.get('year') : this.set('year', v)
135
149
  }
136
150
  month(): number
137
151
  month(v: number): LocalTime
138
152
  month(v?: number): number | LocalTime {
139
- return v === undefined ? this.$date.getMonth() + 1 : this.set('month', v)
153
+ return v === undefined ? this.get('month') : this.set('month', v)
140
154
  }
141
155
  date(): number
142
156
  date(v: number): LocalTime
143
157
  date(v?: number): number | LocalTime {
144
- return v === undefined ? this.$date.getDate() : this.set('day', v)
158
+ return v === undefined ? this.get('day') : this.set('day', v)
145
159
  }
146
160
  hour(): number
147
161
  hour(v: number): LocalTime
148
162
  hour(v?: number): number | LocalTime {
149
- return v === undefined ? this.$date.getHours() : this.set('hour', v)
163
+ return v === undefined ? this.get('hour') : this.set('hour', v)
150
164
  }
151
165
  minute(): number
152
166
  minute(v: number): LocalTime
153
167
  minute(v?: number): number | LocalTime {
154
- return v === undefined ? this.$date.getMinutes() : this.set('minute', v)
168
+ return v === undefined ? this.get('minute') : this.set('minute', v)
155
169
  }
156
170
  second(): number
157
171
  second(v: number): LocalTime
158
172
  second(v?: number): number | LocalTime {
159
- return v === undefined ? this.$date.getSeconds() : this.set('second', v)
173
+ return v === undefined ? this.get('second') : this.set('second', v)
160
174
  }
161
175
 
162
176
  setComponents(c: Partial<LocalTimeComponents>, mutate = false): LocalTime {
163
177
  const d = mutate ? this.$date : new Date(this.$date)
164
178
 
179
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
165
180
  if (c.year) {
166
- d.setFullYear(c.year)
181
+ this.utcMode ? d.setUTCFullYear(c.year) : d.setFullYear(c.year)
167
182
  }
168
183
  if (c.month) {
169
- d.setMonth(c.month - 1)
184
+ this.utcMode ? d.setUTCMonth(c.month - 1) : d.setMonth(c.month - 1)
170
185
  }
171
186
  if (c.day) {
172
- d.setDate(c.day)
187
+ this.utcMode ? d.setUTCDate(c.day) : d.setDate(c.day)
173
188
  }
174
189
  if (c.hour !== undefined) {
175
- d.setHours(c.hour)
190
+ this.utcMode ? d.setUTCHours(c.hour) : d.setHours(c.hour)
176
191
  }
177
192
  if (c.minute !== undefined) {
178
- d.setMinutes(c.minute)
193
+ this.utcMode ? d.setUTCMinutes(c.minute) : d.setMinutes(c.minute)
179
194
  }
180
195
  if (c.second !== undefined) {
181
- d.setSeconds(c.second)
196
+ this.utcMode ? d.setUTCSeconds(c.second) : d.setSeconds(c.second)
182
197
  }
198
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
183
199
 
184
- return mutate ? this : new LocalTime(d)
200
+ return mutate ? this : new LocalTime(d, this.utcMode)
185
201
  }
186
202
 
187
203
  add(num: number, unit: LocalTimeUnit, mutate = false): LocalTime {
@@ -189,7 +205,7 @@ export class LocalTime {
189
205
  }
190
206
 
191
207
  subtract(num: number, unit: LocalTimeUnit, mutate = false): LocalTime {
192
- return this.add(-num, unit, mutate)
208
+ return this.add(num * -1, unit, mutate)
193
209
  }
194
210
 
195
211
  absDiff(other: LocalTimeConfig, unit: LocalTimeUnit): number {
@@ -232,36 +248,25 @@ export class LocalTime {
232
248
  startOf(unit: LocalTimeUnit, mutate = false): LocalTime {
233
249
  if (unit === 'second') return this
234
250
 
235
- if (mutate) {
236
- const d = this.$date
237
- d.setSeconds(0)
238
- if (unit === 'minute') return this
239
- d.setMinutes(0)
240
- if (unit === 'hour') return this
241
- d.setHours(0)
242
- if (unit === 'day') return this
243
- d.setDate(0)
244
- if (unit === 'month') return this
245
- d.setMonth(0)
246
- return this
247
- }
248
-
249
- const c = this.components()
251
+ const d = mutate ? this.$date : new Date(this.$date)
250
252
 
251
- c.second = 0
252
- if (unit === 'year') {
253
- c.month = c.day = 1
254
- c.hour = c.minute = 0
255
- } else if (unit === 'month') {
256
- c.day = 1
257
- c.hour = c.minute = 0
258
- } else if (unit === 'day') {
259
- c.hour = c.minute = 0
260
- } else if (unit === 'hour') {
261
- c.minute = 0
253
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
254
+ this.utcMode ? d.setUTCSeconds(0) : d.setSeconds(0)
255
+ if (unit !== 'minute') {
256
+ this.utcMode ? d.setUTCMinutes(0) : d.setMinutes(0)
257
+ if (unit !== 'hour') {
258
+ this.utcMode ? d.setUTCHours(0) : d.setHours(0)
259
+ if (unit !== 'day') {
260
+ this.utcMode ? d.setUTCDate(0) : d.setDate(0)
261
+ if (unit !== 'month') {
262
+ this.utcMode ? d.setUTCMonth(0) : d.setMonth(0)
263
+ }
264
+ }
265
+ }
262
266
  }
267
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
263
268
 
264
- return LocalTime.fromComponents(c)
269
+ return mutate ? this : new LocalTime(d, this.utcMode)
265
270
  }
266
271
 
267
272
  static sort(items: LocalTime[], mutate = false, descending = false): LocalTime[] {
@@ -329,6 +334,17 @@ export class LocalTime {
329
334
  // todo: endOf
330
335
 
331
336
  components(): LocalTimeComponents {
337
+ if (this.utcMode) {
338
+ return {
339
+ year: this.$date.getUTCFullYear(),
340
+ month: this.$date.getUTCMonth() + 1,
341
+ day: this.$date.getUTCDate(),
342
+ hour: this.$date.getUTCHours(),
343
+ minute: this.$date.getUTCMinutes(),
344
+ second: this.$date.getSeconds(),
345
+ }
346
+ }
347
+
332
348
  return {
333
349
  year: this.$date.getFullYear(),
334
350
  month: this.$date.getMonth() + 1,
@@ -339,46 +355,132 @@ export class LocalTime {
339
355
  }
340
356
  }
341
357
 
358
+ fromNow(now: LocalTimeConfig = LocalTime.now()): string {
359
+ const msDiff = LocalTime.of(now).unixMillis() - this.unixMillis()
360
+
361
+ if (msDiff === 0) return 'now'
362
+
363
+ if (msDiff >= 0) {
364
+ return `${_ms(msDiff)} ago`
365
+ }
366
+
367
+ return `in ${_ms(msDiff * -1)}`
368
+ }
369
+
342
370
  getDate(): Date {
343
371
  return this.$date
344
372
  }
345
373
 
346
374
  clone(): LocalTime {
347
- return new LocalTime(new Date(this.$date))
375
+ return new LocalTime(new Date(this.$date), this.utcMode)
348
376
  }
349
377
 
350
378
  unix(): UnixTimestamp {
351
379
  return Math.floor(this.$date.valueOf() / 1000)
352
380
  }
353
381
 
382
+ unixMillis(): number {
383
+ return this.$date.valueOf()
384
+ }
385
+
354
386
  valueOf(): UnixTimestamp {
355
387
  return Math.floor(this.$date.valueOf() / 1000)
356
388
  }
357
389
 
358
- toISO8601(): IsoDateTime {
359
- return this.$date.toISOString().slice(0, 19)
390
+ toLocalDate(): LocalDate {
391
+ if (this.utcMode) {
392
+ return LocalDate.create(
393
+ this.$date.getUTCFullYear(),
394
+ this.$date.getUTCMonth() + 1,
395
+ this.$date.getUTCDate(),
396
+ )
397
+ }
398
+
399
+ return LocalDate.create(
400
+ this.$date.getFullYear(),
401
+ this.$date.getMonth() + 1,
402
+ this.$date.getDate(),
403
+ )
360
404
  }
361
405
 
362
406
  toPretty(seconds = true): IsoDateTime {
363
- return this.$date
364
- .toISOString()
365
- .slice(0, seconds ? 19 : 16)
366
- .split('T')
367
- .join(' ')
407
+ const { year, month, day, hour, minute, second } = this.components()
408
+
409
+ return (
410
+ [
411
+ String(year).padStart(4, '0'),
412
+ String(month).padStart(2, '0'),
413
+ String(day).padStart(2, '0'),
414
+ ].join('-') +
415
+ ' ' +
416
+ [
417
+ String(hour).padStart(2, '0'),
418
+ String(minute).padStart(2, '0'),
419
+ seconds && String(second).padStart(2, '0'),
420
+ ]
421
+ .filter(Boolean)
422
+ .join(':')
423
+ )
424
+
425
+ // return this.$date
426
+ // .toISOString()
427
+ // .slice(0, seconds ? 19 : 16)
428
+ // .split('T')
429
+ // .join(' ')
430
+ }
431
+
432
+ /**
433
+ * Returns e.g: `1984-06-21T17:56:21`, only the date part of DateTime
434
+ */
435
+ toISODateTime(): IsoDateTime {
436
+ return this.$date.toISOString().slice(0, 19)
437
+ }
438
+
439
+ /**
440
+ * Returns e.g: `1984-06-21`, only the date part of DateTime
441
+ */
442
+ toISODate(): IsoDate {
443
+ const { year, month, day } = this.components()
444
+
445
+ return [
446
+ String(year).padStart(4, '0'),
447
+ String(month).padStart(2, '0'),
448
+ String(day).padStart(2, '0'),
449
+ ].join('-')
450
+
451
+ // return this.$date.toISOString().slice(0, 10)
452
+ }
453
+
454
+ /**
455
+ * Returns e.g: `17:03:15` (or `17:03` with seconds=false)
456
+ */
457
+ toISOTime(seconds = true): string {
458
+ // return this.$date.toISOString().slice(11, seconds ? 19 : 16)
459
+ const { hour, minute, second } = this.components()
460
+
461
+ return [
462
+ String(hour).padStart(2, '0'),
463
+ String(minute).padStart(2, '0'),
464
+ seconds && String(second).padStart(2, '0'),
465
+ ]
466
+ .filter(Boolean)
467
+ .join(':')
368
468
  }
369
469
 
370
470
  /**
371
471
  * Returns e.g: `19840621_1705`
372
472
  */
373
473
  toStringCompact(seconds = false): string {
474
+ const { year, month, day, hour, minute, second } = this.components()
475
+
374
476
  return [
375
- String(this.$date.getFullYear()).padStart(4, '0'),
376
- String(this.$date.getMonth() + 1).padStart(2, '0'),
377
- String(this.$date.getDate()).padStart(2, '0'),
477
+ String(year).padStart(4, '0'),
478
+ String(month).padStart(2, '0'),
479
+ String(day).padStart(2, '0'),
378
480
  '_',
379
- String(this.$date.getHours()).padStart(2, '0'),
380
- String(this.$date.getMinutes()).padStart(2, '0'),
381
- seconds ? String(this.$date.getSeconds()).padStart(2, '0') : '',
481
+ String(hour).padStart(2, '0'),
482
+ String(minute).padStart(2, '0'),
483
+ seconds ? String(second).padStart(2, '0') : '',
382
484
  ].join('')
383
485
  }
384
486