@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,4 +1,6 @@
1
1
  import { _assert } from '../error/assert';
2
+ import { _ms } from '../time/time.util';
3
+ import { LocalDate } from './localDate';
2
4
  /* eslint-disable no-dupe-class-members */
3
5
  // Design choices:
4
6
  // No milliseconds
@@ -13,8 +15,9 @@ import { _assert } from '../error/assert';
13
15
  * @experimental
14
16
  */
15
17
  export class LocalTime {
16
- constructor($date) {
18
+ constructor($date, utcMode) {
17
19
  this.$date = $date;
20
+ this.utcMode = utcMode;
18
21
  }
19
22
  /**
20
23
  * Parses input String into LocalDate.
@@ -27,6 +30,14 @@ export class LocalTime {
27
30
  }
28
31
  return t;
29
32
  }
33
+ utc() {
34
+ this.utcMode = true;
35
+ return this;
36
+ }
37
+ local() {
38
+ this.utcMode = false;
39
+ return this;
40
+ }
30
41
  /**
31
42
  * Returns null if invalid
32
43
  */
@@ -48,106 +59,110 @@ export class LocalTime {
48
59
  // throw new TypeError(`Cannot parse "${d}" into LocalTime`)
49
60
  return null;
50
61
  }
51
- return new LocalTime(date);
62
+ // if (utc) {
63
+ // date.setMinutes(date.getMinutes() + date.getTimezoneOffset())
64
+ // }
65
+ return new LocalTime(date, false);
52
66
  }
53
67
  static isValid(d) {
54
68
  return this.parseOrNull(d) !== null;
55
69
  }
56
- static unix(ts) {
57
- return new LocalTime(new Date(ts * 1000));
58
- }
59
70
  static now() {
60
- return this.of(new Date());
71
+ return new LocalTime(new Date(), false);
61
72
  }
62
73
  static fromComponents(c) {
63
- return new LocalTime(new Date(c.year, c.month - 1, c.day, c.hour, c.minute, c.second));
74
+ return new LocalTime(new Date(c.year, c.month - 1, c.day, c.hour, c.minute, c.second), false);
64
75
  }
65
76
  get(unit) {
66
77
  if (unit === 'year') {
67
- return this.$date.getFullYear();
78
+ return this.utcMode ? this.$date.getUTCFullYear() : this.$date.getFullYear();
68
79
  }
69
80
  if (unit === 'month') {
70
- return this.$date.getMonth() + 1;
81
+ return (this.utcMode ? this.$date.getUTCMonth() : this.$date.getMonth()) + 1;
71
82
  }
72
83
  if (unit === 'day') {
73
- return this.$date.getDate();
84
+ return this.utcMode ? this.$date.getUTCDate() : this.$date.getDate();
74
85
  }
75
86
  if (unit === 'hour') {
76
- return this.$date.getHours();
87
+ return this.utcMode ? this.$date.getUTCHours() : this.$date.getHours();
77
88
  }
78
89
  if (unit === 'minute') {
79
- return this.$date.getMinutes();
90
+ return this.utcMode ? this.$date.getUTCMinutes() : this.$date.getMinutes();
80
91
  }
81
92
  // second
82
- return this.$date.getSeconds();
93
+ return this.utcMode ? this.$date.getUTCSeconds() : this.$date.getSeconds();
83
94
  }
84
95
  set(unit, v, mutate = false) {
85
96
  const t = mutate ? this : this.clone();
97
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
86
98
  if (unit === 'year') {
87
- t.$date.setFullYear(v);
99
+ this.utcMode ? t.$date.setUTCFullYear(v) : t.$date.setFullYear(v);
88
100
  }
89
101
  else if (unit === 'month') {
90
- t.$date.setMonth(v - 1);
102
+ this.utcMode ? t.$date.setUTCMonth(v - 1) : t.$date.setMonth(v - 1);
91
103
  }
92
104
  else if (unit === 'day') {
93
- t.$date.setDate(v);
105
+ this.utcMode ? t.$date.setUTCDate(v) : t.$date.setDate(v);
94
106
  }
95
107
  else if (unit === 'hour') {
96
- t.$date.setHours(v);
108
+ this.utcMode ? t.$date.setUTCHours(v) : t.$date.setHours(v);
97
109
  }
98
110
  else if (unit === 'minute') {
99
- t.$date.setMinutes(v);
111
+ this.utcMode ? t.$date.setUTCMinutes(v) : t.$date.setMinutes(v);
100
112
  }
101
113
  else if (unit === 'second') {
102
- t.$date.setSeconds(v);
114
+ this.utcMode ? t.$date.setUTCSeconds(v) : t.$date.setSeconds(v);
103
115
  }
116
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
104
117
  return t;
105
118
  }
106
119
  year(v) {
107
- return v === undefined ? this.$date.getFullYear() : this.set('year', v);
120
+ return v === undefined ? this.get('year') : this.set('year', v);
108
121
  }
109
122
  month(v) {
110
- return v === undefined ? this.$date.getMonth() + 1 : this.set('month', v);
123
+ return v === undefined ? this.get('month') : this.set('month', v);
111
124
  }
112
125
  date(v) {
113
- return v === undefined ? this.$date.getDate() : this.set('day', v);
126
+ return v === undefined ? this.get('day') : this.set('day', v);
114
127
  }
115
128
  hour(v) {
116
- return v === undefined ? this.$date.getHours() : this.set('hour', v);
129
+ return v === undefined ? this.get('hour') : this.set('hour', v);
117
130
  }
118
131
  minute(v) {
119
- return v === undefined ? this.$date.getMinutes() : this.set('minute', v);
132
+ return v === undefined ? this.get('minute') : this.set('minute', v);
120
133
  }
121
134
  second(v) {
122
- return v === undefined ? this.$date.getSeconds() : this.set('second', v);
135
+ return v === undefined ? this.get('second') : this.set('second', v);
123
136
  }
124
137
  setComponents(c, mutate = false) {
125
138
  const d = mutate ? this.$date : new Date(this.$date);
139
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
126
140
  if (c.year) {
127
- d.setFullYear(c.year);
141
+ this.utcMode ? d.setUTCFullYear(c.year) : d.setFullYear(c.year);
128
142
  }
129
143
  if (c.month) {
130
- d.setMonth(c.month - 1);
144
+ this.utcMode ? d.setUTCMonth(c.month - 1) : d.setMonth(c.month - 1);
131
145
  }
132
146
  if (c.day) {
133
- d.setDate(c.day);
147
+ this.utcMode ? d.setUTCDate(c.day) : d.setDate(c.day);
134
148
  }
135
149
  if (c.hour !== undefined) {
136
- d.setHours(c.hour);
150
+ this.utcMode ? d.setUTCHours(c.hour) : d.setHours(c.hour);
137
151
  }
138
152
  if (c.minute !== undefined) {
139
- d.setMinutes(c.minute);
153
+ this.utcMode ? d.setUTCMinutes(c.minute) : d.setMinutes(c.minute);
140
154
  }
141
155
  if (c.second !== undefined) {
142
- d.setSeconds(c.second);
156
+ this.utcMode ? d.setUTCSeconds(c.second) : d.setSeconds(c.second);
143
157
  }
144
- return mutate ? this : new LocalTime(d);
158
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
159
+ return mutate ? this : new LocalTime(d, this.utcMode);
145
160
  }
146
161
  add(num, unit, mutate = false) {
147
162
  return this.set(unit, this.get(unit) + num, mutate);
148
163
  }
149
164
  subtract(num, unit, mutate = false) {
150
- return this.add(-num, unit, mutate);
165
+ return this.add(num * -1, unit, mutate);
151
166
  }
152
167
  absDiff(other, unit) {
153
168
  return Math.abs(this.diff(other, unit));
@@ -185,40 +200,23 @@ export class LocalTime {
185
200
  startOf(unit, mutate = false) {
186
201
  if (unit === 'second')
187
202
  return this;
188
- if (mutate) {
189
- const d = this.$date;
190
- d.setSeconds(0);
191
- if (unit === 'minute')
192
- return this;
193
- d.setMinutes(0);
194
- if (unit === 'hour')
195
- return this;
196
- d.setHours(0);
197
- if (unit === 'day')
198
- return this;
199
- d.setDate(0);
200
- if (unit === 'month')
201
- return this;
202
- d.setMonth(0);
203
- return this;
204
- }
205
- const c = this.components();
206
- c.second = 0;
207
- if (unit === 'year') {
208
- c.month = c.day = 1;
209
- c.hour = c.minute = 0;
210
- }
211
- else if (unit === 'month') {
212
- c.day = 1;
213
- c.hour = c.minute = 0;
214
- }
215
- else if (unit === 'day') {
216
- c.hour = c.minute = 0;
217
- }
218
- else if (unit === 'hour') {
219
- c.minute = 0;
220
- }
221
- return LocalTime.fromComponents(c);
203
+ const d = mutate ? this.$date : new Date(this.$date);
204
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
205
+ this.utcMode ? d.setUTCSeconds(0) : d.setSeconds(0);
206
+ if (unit !== 'minute') {
207
+ this.utcMode ? d.setUTCMinutes(0) : d.setMinutes(0);
208
+ if (unit !== 'hour') {
209
+ this.utcMode ? d.setUTCHours(0) : d.setHours(0);
210
+ if (unit !== 'day') {
211
+ this.utcMode ? d.setUTCDate(0) : d.setDate(0);
212
+ if (unit !== 'month') {
213
+ this.utcMode ? d.setUTCMonth(0) : d.setMonth(0);
214
+ }
215
+ }
216
+ }
217
+ }
218
+ /* eslint-enable @typescript-eslint/no-unused-expressions */
219
+ return mutate ? this : new LocalTime(d, this.utcMode);
222
220
  }
223
221
  static sort(items, mutate = false, descending = false) {
224
222
  const mod = descending ? -1 : 1;
@@ -273,6 +271,16 @@ export class LocalTime {
273
271
  }
274
272
  // todo: endOf
275
273
  components() {
274
+ if (this.utcMode) {
275
+ return {
276
+ year: this.$date.getUTCFullYear(),
277
+ month: this.$date.getUTCMonth() + 1,
278
+ day: this.$date.getUTCDate(),
279
+ hour: this.$date.getUTCHours(),
280
+ minute: this.$date.getUTCMinutes(),
281
+ second: this.$date.getSeconds(),
282
+ };
283
+ }
276
284
  return {
277
285
  year: this.$date.getFullYear(),
278
286
  month: this.$date.getMonth() + 1,
@@ -282,40 +290,102 @@ export class LocalTime {
282
290
  second: this.$date.getSeconds(),
283
291
  };
284
292
  }
293
+ fromNow(now = LocalTime.now()) {
294
+ const msDiff = LocalTime.of(now).unixMillis() - this.unixMillis();
295
+ if (msDiff === 0)
296
+ return 'now';
297
+ if (msDiff >= 0) {
298
+ return `${_ms(msDiff)} ago`;
299
+ }
300
+ return `in ${_ms(msDiff * -1)}`;
301
+ }
285
302
  getDate() {
286
303
  return this.$date;
287
304
  }
288
305
  clone() {
289
- return new LocalTime(new Date(this.$date));
306
+ return new LocalTime(new Date(this.$date), this.utcMode);
290
307
  }
291
308
  unix() {
292
309
  return Math.floor(this.$date.valueOf() / 1000);
293
310
  }
311
+ unixMillis() {
312
+ return this.$date.valueOf();
313
+ }
294
314
  valueOf() {
295
315
  return Math.floor(this.$date.valueOf() / 1000);
296
316
  }
297
- toISO8601() {
298
- return this.$date.toISOString().slice(0, 19);
317
+ toLocalDate() {
318
+ if (this.utcMode) {
319
+ return LocalDate.create(this.$date.getUTCFullYear(), this.$date.getUTCMonth() + 1, this.$date.getUTCDate());
320
+ }
321
+ return LocalDate.create(this.$date.getFullYear(), this.$date.getMonth() + 1, this.$date.getDate());
299
322
  }
300
323
  toPretty(seconds = true) {
301
- return this.$date
302
- .toISOString()
303
- .slice(0, seconds ? 19 : 16)
304
- .split('T')
305
- .join(' ');
324
+ const { year, month, day, hour, minute, second } = this.components();
325
+ return ([
326
+ String(year).padStart(4, '0'),
327
+ String(month).padStart(2, '0'),
328
+ String(day).padStart(2, '0'),
329
+ ].join('-') +
330
+ ' ' +
331
+ [
332
+ String(hour).padStart(2, '0'),
333
+ String(minute).padStart(2, '0'),
334
+ seconds && String(second).padStart(2, '0'),
335
+ ]
336
+ .filter(Boolean)
337
+ .join(':'));
338
+ // return this.$date
339
+ // .toISOString()
340
+ // .slice(0, seconds ? 19 : 16)
341
+ // .split('T')
342
+ // .join(' ')
343
+ }
344
+ /**
345
+ * Returns e.g: `1984-06-21T17:56:21`, only the date part of DateTime
346
+ */
347
+ toISODateTime() {
348
+ return this.$date.toISOString().slice(0, 19);
349
+ }
350
+ /**
351
+ * Returns e.g: `1984-06-21`, only the date part of DateTime
352
+ */
353
+ toISODate() {
354
+ const { year, month, day } = this.components();
355
+ return [
356
+ String(year).padStart(4, '0'),
357
+ String(month).padStart(2, '0'),
358
+ String(day).padStart(2, '0'),
359
+ ].join('-');
360
+ // return this.$date.toISOString().slice(0, 10)
361
+ }
362
+ /**
363
+ * Returns e.g: `17:03:15` (or `17:03` with seconds=false)
364
+ */
365
+ toISOTime(seconds = true) {
366
+ // return this.$date.toISOString().slice(11, seconds ? 19 : 16)
367
+ const { hour, minute, second } = this.components();
368
+ return [
369
+ String(hour).padStart(2, '0'),
370
+ String(minute).padStart(2, '0'),
371
+ seconds && String(second).padStart(2, '0'),
372
+ ]
373
+ .filter(Boolean)
374
+ .join(':');
306
375
  }
307
376
  /**
308
377
  * Returns e.g: `19840621_1705`
309
378
  */
310
379
  toStringCompact(seconds = false) {
380
+ const { year, month, day, hour, minute, second } = this.components();
311
381
  return [
312
- String(this.$date.getFullYear()).padStart(4, '0'),
313
- String(this.$date.getMonth() + 1).padStart(2, '0'),
314
- String(this.$date.getDate()).padStart(2, '0'),
382
+ String(year).padStart(4, '0'),
383
+ String(month).padStart(2, '0'),
384
+ String(day).padStart(2, '0'),
315
385
  '_',
316
- String(this.$date.getHours()).padStart(2, '0'),
317
- String(this.$date.getMinutes()).padStart(2, '0'),
318
- seconds ? String(this.$date.getSeconds()).padStart(2, '0') : '',
386
+ String(hour).padStart(2, '0'),
387
+ String(minute).padStart(2, '0'),
388
+ seconds ? String(second).padStart(2, '0') : '',
319
389
  ].join('');
320
390
  }
321
391
  toString() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.91.0",
3
+ "version": "14.92.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -1,6 +1,7 @@
1
1
  import { _assert } from '../error/assert'
2
2
  import { Sequence } from '../seq/seq'
3
- import { END, IsoDate } from '../types'
3
+ import { END, IsoDate, UnixTimestamp } from '../types'
4
+ import { LocalTime } from './localTime'
4
5
 
5
6
  export type LocalDateUnit = 'year' | 'month' | 'day'
6
7
 
@@ -46,6 +47,10 @@ export class LocalDate {
46
47
  return new LocalDate(d.getFullYear(), d.getMonth() + 1, d.getDate())
47
48
  }
48
49
 
50
+ static fromDateUTC(d: Date): LocalDate {
51
+ return new LocalDate(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate())
52
+ }
53
+
49
54
  /**
50
55
  * Returns null if invalid.
51
56
  */
@@ -78,6 +83,10 @@ export class LocalDate {
78
83
  return this.fromDate(new Date())
79
84
  }
80
85
 
86
+ static todayUTC(): LocalDate {
87
+ return this.fromDateUTC(new Date())
88
+ }
89
+
81
90
  static sort(items: LocalDate[], mutate = false, descending = false): LocalDate[] {
82
91
  const mod = descending ? -1 : 1
83
92
  return (mutate ? items : [...items]).sort((a, b) => a.cmp(b) * mod)
@@ -356,6 +365,14 @@ export class LocalDate {
356
365
  return new Date(this.year, this.month - 1, this.day)
357
366
  }
358
367
 
368
+ toLocalTime(): LocalTime {
369
+ return LocalTime.of(this.toDate())
370
+ }
371
+
372
+ toISODate(): IsoDate {
373
+ return this.toString()
374
+ }
375
+
359
376
  toString(): IsoDate {
360
377
  return [
361
378
  String(this.year).padStart(4, '0'),
@@ -372,6 +389,15 @@ export class LocalDate {
372
389
  ].join('')
373
390
  }
374
391
 
392
+ // May be not optimal, as LocalTime better suits it
393
+ unix(): UnixTimestamp {
394
+ return Math.floor(this.toDate().valueOf() / 1000)
395
+ }
396
+
397
+ unixMillis(): number {
398
+ return this.toDate().valueOf()
399
+ }
400
+
375
401
  toJSON(): IsoDate {
376
402
  return this.toString()
377
403
  }