@naturalcycles/js-lib 14.99.0 → 14.99.1

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.
@@ -60,7 +60,7 @@ export declare class LocalDate {
60
60
  */
61
61
  absDiff(d: LocalDateConfig, unit: LocalDateUnit): number;
62
62
  /**
63
- * Returns the number of **full** units difference (aka `Math.ceil`).
63
+ * Returns the number of **full** units difference (aka `Math.floor`).
64
64
  *
65
65
  * a.diff(b) means "a minus b"
66
66
  */
@@ -205,44 +205,51 @@ class LocalDate {
205
205
  return Math.abs(this.diff(d, unit));
206
206
  }
207
207
  /**
208
- * Returns the number of **full** units difference (aka `Math.ceil`).
208
+ * Returns the number of **full** units difference (aka `Math.floor`).
209
209
  *
210
210
  * a.diff(b) means "a minus b"
211
211
  */
212
212
  diff(d, unit) {
213
213
  d = LocalDate.of(d);
214
+ const sign = this.cmp(d);
215
+ if (!sign)
216
+ return 0;
217
+ // Put items in descending order: "big minus small"
218
+ const [big, small] = sign === 1 ? [this, d] : [d, this];
214
219
  if (unit === 'year') {
215
- return this.$year - d.$year;
220
+ let years = big.$year - small.$year;
221
+ if (big.$month < small.$month || (big.$month === small.$month && big.$day < small.$day)) {
222
+ years--;
223
+ }
224
+ return years * sign || 0;
216
225
  }
217
226
  if (unit === 'month') {
218
- return (this.$year - d.$year) * 12 + (this.$month - d.$month);
227
+ let months = (big.$year - small.$year) * 12 + (big.$month - small.$month);
228
+ if (big.$day < small.$day)
229
+ months--;
230
+ return months * sign || 0;
219
231
  }
220
232
  // unit is 'day' or 'week'
221
- let days = this.$day - d.$day;
222
- if (d.$year < this.$year) {
223
- for (let year = d.$year; year < this.$year; year++) {
224
- days += LocalDate.getYearLength(year);
225
- }
226
- }
227
- else if (this.$year < d.$year) {
228
- for (let year = this.$year; year < d.$year; year++) {
229
- days -= LocalDate.getYearLength(year);
230
- }
233
+ let days = big.$day - small.$day;
234
+ // If small date is after 1st of March - next year's "leapness" should be used
235
+ const offsetYear = small.$month >= 3 ? 1 : 0;
236
+ for (let year = small.$year; year < big.$year; year++) {
237
+ days += LocalDate.getYearLength(year + offsetYear);
231
238
  }
232
- if (d.$month < this.$month) {
233
- for (let month = d.$month; month < this.$month; month++) {
234
- days += LocalDate.getMonthLength(this.$year, month);
239
+ if (small.$month < big.$month) {
240
+ for (let month = small.$month; month < big.$month; month++) {
241
+ days += LocalDate.getMonthLength(big.$year, month);
235
242
  }
236
243
  }
237
- else if (this.$month < d.$month) {
238
- for (let month = this.$month; month < d.$month; month++) {
239
- days -= LocalDate.getMonthLength(d.$year, month);
244
+ else if (big.$month < small.$month) {
245
+ for (let month = big.$month; month < small.$month; month++) {
246
+ days -= LocalDate.getMonthLength(big.$year, month);
240
247
  }
241
248
  }
242
249
  if (unit === 'week') {
243
- return Math.floor(days / 7);
250
+ return Math.trunc(days / 7) * sign || 0;
244
251
  }
245
- return days;
252
+ return days * sign || 0;
246
253
  }
247
254
  add(num, unit, mutate = false) {
248
255
  let { $day, $month, $year } = this;
@@ -16,6 +16,7 @@ var ISODayOfWeek;
16
16
  })(ISODayOfWeek = exports.ISODayOfWeek || (exports.ISODayOfWeek = {}));
17
17
  const weekStartsOn = 1; // mon, as per ISO
18
18
  const MILLISECONDS_IN_WEEK = 604800000;
19
+ const SECONDS_IN_DAY = 86400;
19
20
  // const MILLISECONDS_IN_DAY = 86400000
20
21
  // const MILLISECONDS_IN_MINUTE = 60000
21
22
  const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
@@ -224,24 +225,43 @@ class LocalTime {
224
225
  }
225
226
  diff(other, unit) {
226
227
  const date2 = LocalTime.parseToDate(other);
227
- if (unit === 'year') {
228
- return this.$date.getFullYear() - date2.getFullYear();
229
- }
230
- if (unit === 'month') {
231
- return ((this.$date.getFullYear() - date2.getFullYear()) * 12 +
232
- this.$date.getMonth() -
233
- date2.getMonth());
234
- }
235
228
  const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
229
+ if (!secDiff)
230
+ return 0;
231
+ if (unit === 'year' || unit === 'month') {
232
+ const sign = secDiff > 0 ? 1 : -1;
233
+ // Put items in descending order: "big minus small"
234
+ const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date];
235
+ if (unit === 'year') {
236
+ let years = big.getFullYear() - small.getFullYear();
237
+ const big2 = new Date(big);
238
+ const small2 = new Date(small);
239
+ big2.setFullYear(1584);
240
+ small2.setFullYear(1584);
241
+ if (big2 < small2)
242
+ years--;
243
+ return years * sign || 0;
244
+ }
245
+ if (unit === 'month') {
246
+ let months = (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth();
247
+ const big2 = new Date(big);
248
+ const small2 = new Date(small);
249
+ big2.setFullYear(1584, 0);
250
+ small2.setFullYear(1584, 0);
251
+ if (big2 < small2)
252
+ months--;
253
+ return months * sign || 0;
254
+ }
255
+ }
236
256
  let r;
237
257
  if (unit === 'day') {
238
- r = secDiff / (24 * 60 * 60);
258
+ r = secDiff / SECONDS_IN_DAY;
239
259
  }
240
260
  else if (unit === 'week') {
241
261
  r = secDiff / (7 * 24 * 60 * 60);
242
262
  }
243
263
  else if (unit === 'hour') {
244
- r = secDiff / (60 * 60);
264
+ r = secDiff / 3600;
245
265
  }
246
266
  else if (unit === 'minute') {
247
267
  r = secDiff / 60;
@@ -250,10 +270,8 @@ class LocalTime {
250
270
  // unit === 'second'
251
271
  r = secDiff;
252
272
  }
253
- r = Math.trunc(r);
254
- if (Object.is(r, -0))
255
- return 0;
256
- return r;
273
+ // `|| 0` is to avoid returning -0
274
+ return Math.trunc(r) || 0;
257
275
  }
258
276
  startOf(unit, mutate = false) {
259
277
  if (unit === 'second')
@@ -202,44 +202,51 @@ export class LocalDate {
202
202
  return Math.abs(this.diff(d, unit));
203
203
  }
204
204
  /**
205
- * Returns the number of **full** units difference (aka `Math.ceil`).
205
+ * Returns the number of **full** units difference (aka `Math.floor`).
206
206
  *
207
207
  * a.diff(b) means "a minus b"
208
208
  */
209
209
  diff(d, unit) {
210
210
  d = LocalDate.of(d);
211
+ const sign = this.cmp(d);
212
+ if (!sign)
213
+ return 0;
214
+ // Put items in descending order: "big minus small"
215
+ const [big, small] = sign === 1 ? [this, d] : [d, this];
211
216
  if (unit === 'year') {
212
- return this.$year - d.$year;
217
+ let years = big.$year - small.$year;
218
+ if (big.$month < small.$month || (big.$month === small.$month && big.$day < small.$day)) {
219
+ years--;
220
+ }
221
+ return years * sign || 0;
213
222
  }
214
223
  if (unit === 'month') {
215
- return (this.$year - d.$year) * 12 + (this.$month - d.$month);
224
+ let months = (big.$year - small.$year) * 12 + (big.$month - small.$month);
225
+ if (big.$day < small.$day)
226
+ months--;
227
+ return months * sign || 0;
216
228
  }
217
229
  // unit is 'day' or 'week'
218
- let days = this.$day - d.$day;
219
- if (d.$year < this.$year) {
220
- for (let year = d.$year; year < this.$year; year++) {
221
- days += LocalDate.getYearLength(year);
222
- }
223
- }
224
- else if (this.$year < d.$year) {
225
- for (let year = this.$year; year < d.$year; year++) {
226
- days -= LocalDate.getYearLength(year);
227
- }
230
+ let days = big.$day - small.$day;
231
+ // If small date is after 1st of March - next year's "leapness" should be used
232
+ const offsetYear = small.$month >= 3 ? 1 : 0;
233
+ for (let year = small.$year; year < big.$year; year++) {
234
+ days += LocalDate.getYearLength(year + offsetYear);
228
235
  }
229
- if (d.$month < this.$month) {
230
- for (let month = d.$month; month < this.$month; month++) {
231
- days += LocalDate.getMonthLength(this.$year, month);
236
+ if (small.$month < big.$month) {
237
+ for (let month = small.$month; month < big.$month; month++) {
238
+ days += LocalDate.getMonthLength(big.$year, month);
232
239
  }
233
240
  }
234
- else if (this.$month < d.$month) {
235
- for (let month = this.$month; month < d.$month; month++) {
236
- days -= LocalDate.getMonthLength(d.$year, month);
241
+ else if (big.$month < small.$month) {
242
+ for (let month = big.$month; month < small.$month; month++) {
243
+ days -= LocalDate.getMonthLength(big.$year, month);
237
244
  }
238
245
  }
239
246
  if (unit === 'week') {
240
- return Math.floor(days / 7);
247
+ return Math.trunc(days / 7) * sign || 0;
241
248
  }
242
- return days;
249
+ return days * sign || 0;
243
250
  }
244
251
  add(num, unit, mutate = false) {
245
252
  let { $day, $month, $year } = this;
@@ -13,6 +13,7 @@ export var ISODayOfWeek;
13
13
  })(ISODayOfWeek || (ISODayOfWeek = {}));
14
14
  const weekStartsOn = 1; // mon, as per ISO
15
15
  const MILLISECONDS_IN_WEEK = 604800000;
16
+ const SECONDS_IN_DAY = 86400;
16
17
  // const MILLISECONDS_IN_DAY = 86400000
17
18
  // const MILLISECONDS_IN_MINUTE = 60000
18
19
  const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7]);
@@ -221,24 +222,43 @@ export class LocalTime {
221
222
  }
222
223
  diff(other, unit) {
223
224
  const date2 = LocalTime.parseToDate(other);
224
- if (unit === 'year') {
225
- return this.$date.getFullYear() - date2.getFullYear();
226
- }
227
- if (unit === 'month') {
228
- return ((this.$date.getFullYear() - date2.getFullYear()) * 12 +
229
- this.$date.getMonth() -
230
- date2.getMonth());
231
- }
232
225
  const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000;
226
+ if (!secDiff)
227
+ return 0;
228
+ if (unit === 'year' || unit === 'month') {
229
+ const sign = secDiff > 0 ? 1 : -1;
230
+ // Put items in descending order: "big minus small"
231
+ const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date];
232
+ if (unit === 'year') {
233
+ let years = big.getFullYear() - small.getFullYear();
234
+ const big2 = new Date(big);
235
+ const small2 = new Date(small);
236
+ big2.setFullYear(1584);
237
+ small2.setFullYear(1584);
238
+ if (big2 < small2)
239
+ years--;
240
+ return years * sign || 0;
241
+ }
242
+ if (unit === 'month') {
243
+ let months = (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth();
244
+ const big2 = new Date(big);
245
+ const small2 = new Date(small);
246
+ big2.setFullYear(1584, 0);
247
+ small2.setFullYear(1584, 0);
248
+ if (big2 < small2)
249
+ months--;
250
+ return months * sign || 0;
251
+ }
252
+ }
233
253
  let r;
234
254
  if (unit === 'day') {
235
- r = secDiff / (24 * 60 * 60);
255
+ r = secDiff / SECONDS_IN_DAY;
236
256
  }
237
257
  else if (unit === 'week') {
238
258
  r = secDiff / (7 * 24 * 60 * 60);
239
259
  }
240
260
  else if (unit === 'hour') {
241
- r = secDiff / (60 * 60);
261
+ r = secDiff / 3600;
242
262
  }
243
263
  else if (unit === 'minute') {
244
264
  r = secDiff / 60;
@@ -247,10 +267,8 @@ export class LocalTime {
247
267
  // unit === 'second'
248
268
  r = secDiff;
249
269
  }
250
- r = Math.trunc(r);
251
- if (Object.is(r, -0))
252
- return 0;
253
- return r;
270
+ // `|| 0` is to avoid returning -0
271
+ return Math.trunc(r) || 0;
254
272
  }
255
273
  startOf(unit, mutate = false) {
256
274
  if (unit === 'second')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.99.0",
3
+ "version": "14.99.1",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "build-prod": "build-prod-esm-cjs",
@@ -253,49 +253,59 @@ export class LocalDate {
253
253
  }
254
254
 
255
255
  /**
256
- * Returns the number of **full** units difference (aka `Math.ceil`).
256
+ * Returns the number of **full** units difference (aka `Math.floor`).
257
257
  *
258
258
  * a.diff(b) means "a minus b"
259
259
  */
260
260
  diff(d: LocalDateConfig, unit: LocalDateUnit): number {
261
261
  d = LocalDate.of(d)
262
262
 
263
+ const sign = this.cmp(d)
264
+ if (!sign) return 0
265
+
266
+ // Put items in descending order: "big minus small"
267
+ const [big, small] = sign === 1 ? [this, d] : [d, this]
268
+
263
269
  if (unit === 'year') {
264
- return this.$year - d.$year
270
+ let years = big.$year - small.$year
271
+
272
+ if (big.$month < small.$month || (big.$month === small.$month && big.$day < small.$day)) {
273
+ years--
274
+ }
275
+
276
+ return years * sign || 0
265
277
  }
266
278
 
267
279
  if (unit === 'month') {
268
- return (this.$year - d.$year) * 12 + (this.$month - d.$month)
280
+ let months = (big.$year - small.$year) * 12 + (big.$month - small.$month)
281
+ if (big.$day < small.$day) months--
282
+ return months * sign || 0
269
283
  }
270
284
 
271
285
  // unit is 'day' or 'week'
272
- let days = this.$day - d.$day
286
+ let days = big.$day - small.$day
273
287
 
274
- if (d.$year < this.$year) {
275
- for (let year = d.$year; year < this.$year; year++) {
276
- days += LocalDate.getYearLength(year)
277
- }
278
- } else if (this.$year < d.$year) {
279
- for (let year = this.$year; year < d.$year; year++) {
280
- days -= LocalDate.getYearLength(year)
281
- }
288
+ // If small date is after 1st of March - next year's "leapness" should be used
289
+ const offsetYear = small.$month >= 3 ? 1 : 0
290
+ for (let year = small.$year; year < big.$year; year++) {
291
+ days += LocalDate.getYearLength(year + offsetYear)
282
292
  }
283
293
 
284
- if (d.$month < this.$month) {
285
- for (let month = d.$month; month < this.$month; month++) {
286
- days += LocalDate.getMonthLength(this.$year, month)
294
+ if (small.$month < big.$month) {
295
+ for (let month = small.$month; month < big.$month; month++) {
296
+ days += LocalDate.getMonthLength(big.$year, month)
287
297
  }
288
- } else if (this.$month < d.$month) {
289
- for (let month = this.$month; month < d.$month; month++) {
290
- days -= LocalDate.getMonthLength(d.$year, month)
298
+ } else if (big.$month < small.$month) {
299
+ for (let month = big.$month; month < small.$month; month++) {
300
+ days -= LocalDate.getMonthLength(big.$year, month)
291
301
  }
292
302
  }
293
303
 
294
304
  if (unit === 'week') {
295
- return Math.floor(days / 7)
305
+ return Math.trunc(days / 7) * sign || 0
296
306
  }
297
307
 
298
- return days
308
+ return days * sign || 0
299
309
  }
300
310
 
301
311
  add(num: number, unit: LocalDateUnit, mutate = false): LocalDate {
@@ -29,6 +29,7 @@ export interface LocalTimeComponents {
29
29
 
30
30
  const weekStartsOn = 1 // mon, as per ISO
31
31
  const MILLISECONDS_IN_WEEK = 604800000
32
+ const SECONDS_IN_DAY = 86400
32
33
  // const MILLISECONDS_IN_DAY = 86400000
33
34
  // const MILLISECONDS_IN_MINUTE = 60000
34
35
  const VALID_DAYS_OF_WEEK = new Set([1, 2, 3, 4, 5, 6, 7])
@@ -281,26 +282,45 @@ export class LocalTime {
281
282
  diff(other: LocalTimeConfig, unit: LocalTimeUnit): number {
282
283
  const date2 = LocalTime.parseToDate(other)
283
284
 
284
- if (unit === 'year') {
285
- return this.$date.getFullYear() - date2.getFullYear()
286
- }
287
- if (unit === 'month') {
288
- return (
289
- (this.$date.getFullYear() - date2.getFullYear()) * 12 +
290
- this.$date.getMonth() -
291
- date2.getMonth()
292
- )
285
+ const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
286
+ if (!secDiff) return 0
287
+
288
+ if (unit === 'year' || unit === 'month') {
289
+ const sign = secDiff > 0 ? 1 : -1
290
+
291
+ // Put items in descending order: "big minus small"
292
+ const [big, small] = sign === 1 ? [this.$date, date2] : [date2, this.$date]
293
+
294
+ if (unit === 'year') {
295
+ let years = big.getFullYear() - small.getFullYear()
296
+ const big2 = new Date(big)
297
+ const small2 = new Date(small)
298
+ big2.setFullYear(1584)
299
+ small2.setFullYear(1584)
300
+ if (big2 < small2) years--
301
+ return years * sign || 0
302
+ }
303
+
304
+ if (unit === 'month') {
305
+ let months =
306
+ (big.getFullYear() - small.getFullYear()) * 12 + big.getMonth() - small.getMonth()
307
+ const big2 = new Date(big)
308
+ const small2 = new Date(small)
309
+ big2.setFullYear(1584, 0)
310
+ small2.setFullYear(1584, 0)
311
+ if (big2 < small2) months--
312
+ return months * sign || 0
313
+ }
293
314
  }
294
315
 
295
- const secDiff = (this.$date.valueOf() - date2.valueOf()) / 1000
296
316
  let r
297
317
 
298
318
  if (unit === 'day') {
299
- r = secDiff / (24 * 60 * 60)
319
+ r = secDiff / SECONDS_IN_DAY
300
320
  } else if (unit === 'week') {
301
321
  r = secDiff / (7 * 24 * 60 * 60)
302
322
  } else if (unit === 'hour') {
303
- r = secDiff / (60 * 60)
323
+ r = secDiff / 3600
304
324
  } else if (unit === 'minute') {
305
325
  r = secDiff / 60
306
326
  } else {
@@ -308,9 +328,8 @@ export class LocalTime {
308
328
  r = secDiff
309
329
  }
310
330
 
311
- r = Math.trunc(r)
312
- if (Object.is(r, -0)) return 0
313
- return r
331
+ // `|| 0` is to avoid returning -0
332
+ return Math.trunc(r) || 0
314
333
  }
315
334
 
316
335
  startOf(unit: LocalTimeUnit, mutate = false): LocalTime {