@tim-code/my-util 0.7.1 → 0.7.3
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.
- package/package.json +1 -1
- package/src/promise.js +4 -4
- package/src/promise.test.js +7 -7
- package/src/time.js +10 -18
- package/src/time.test.js +29 -54
package/package.json
CHANGED
package/src/promise.js
CHANGED
|
@@ -109,11 +109,11 @@ export async function allSettled(
|
|
|
109
109
|
await limiter?.(elements.length)
|
|
110
110
|
}
|
|
111
111
|
if (throws && errors.length) {
|
|
112
|
-
const string = errors.map((error) => error
|
|
112
|
+
const string = errors.map((error) => error?.message ?? error).join("; ")
|
|
113
113
|
const resultError = new PromiseAllError(string)
|
|
114
|
-
const {
|
|
115
|
-
if (
|
|
116
|
-
resultError.stack =
|
|
114
|
+
const { stack } = errors.find((error) => error?.stack) ?? {}
|
|
115
|
+
if (stack) {
|
|
116
|
+
resultError.stack = stack
|
|
117
117
|
}
|
|
118
118
|
throw resultError
|
|
119
119
|
}
|
package/src/promise.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jest } from "@jest/globals"
|
|
3
3
|
|
|
4
4
|
// Exported API under test:
|
|
5
|
-
// -
|
|
5
|
+
// - classes: PollError, PromiseAllError
|
|
6
6
|
// - functions: poll, sleep, allSettled, allPatiently, intervalLimiter, alert, throwFirstReject
|
|
7
7
|
|
|
8
8
|
import {
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
intervalLimiter,
|
|
13
13
|
poll,
|
|
14
14
|
PollError,
|
|
15
|
+
PromiseAllError,
|
|
15
16
|
sleep,
|
|
16
17
|
throwFirstReject,
|
|
17
18
|
} from "./promise.js"
|
|
@@ -240,13 +241,12 @@ describe("allSettled", () => {
|
|
|
240
241
|
expect(result.results.every((r) => r.status === "fulfilled")).toBe(true)
|
|
241
242
|
})
|
|
242
243
|
|
|
243
|
-
it("throws joined error message when throws=true and adopts
|
|
244
|
-
const
|
|
245
|
-
eWithTrace.trace = ["trace line 1", "trace line 2"]
|
|
244
|
+
it("throws joined error message when throws=true and adopts stack from first error", async () => {
|
|
245
|
+
const e1 = new Error("e1")
|
|
246
246
|
const e2 = new Error("third")
|
|
247
247
|
const arr = [1, 2, 3]
|
|
248
248
|
const cb = (x) => {
|
|
249
|
-
if (x === 1) return Promise.reject(
|
|
249
|
+
if (x === 1) return Promise.reject(e1)
|
|
250
250
|
if (x === 2) return x // fulfilled
|
|
251
251
|
return Promise.reject(e2)
|
|
252
252
|
}
|
|
@@ -256,9 +256,9 @@ describe("allSettled", () => {
|
|
|
256
256
|
} catch (e) {
|
|
257
257
|
thrown = e
|
|
258
258
|
}
|
|
259
|
-
expect(thrown).toBeInstanceOf(
|
|
259
|
+
expect(thrown).toBeInstanceOf(PromiseAllError)
|
|
260
260
|
expect(thrown.message).toBe("e1; third")
|
|
261
|
-
expect(thrown.stack).toBe(
|
|
261
|
+
expect(thrown.stack).toBe(e1.stack)
|
|
262
262
|
})
|
|
263
263
|
})
|
|
264
264
|
|
package/src/time.js
CHANGED
|
@@ -44,6 +44,16 @@ export function getTime({ floorMinute, timestamp, timeZone = false } = {}) {
|
|
|
44
44
|
return getEasternTime({ floorMinute, timestamp, timeZone })
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Get Unix timestamp for a UTC date string.
|
|
49
|
+
* @param {string} utc UTC date time: "YYYY-MM-DDTHH:mm:ssZ" or with UTC offset
|
|
50
|
+
* @returns {number} Seconds since epoch
|
|
51
|
+
*/
|
|
52
|
+
export function getUnixTimestamp(utc) {
|
|
53
|
+
const timestamp = Math.floor(new Date(utc).getTime() / 1000)
|
|
54
|
+
return timestamp
|
|
55
|
+
}
|
|
56
|
+
|
|
47
57
|
/**
|
|
48
58
|
* Get today's date in YYYY-MM-DD format using local time.
|
|
49
59
|
* @returns {string}
|
|
@@ -96,15 +106,6 @@ export function isDateString(string) {
|
|
|
96
106
|
)
|
|
97
107
|
}
|
|
98
108
|
|
|
99
|
-
/**
|
|
100
|
-
* @deprecated Prefer isDateString()
|
|
101
|
-
* @param {string} string
|
|
102
|
-
* @returns {boolean}
|
|
103
|
-
*/
|
|
104
|
-
export function isDate(string) {
|
|
105
|
-
return isDateString(string)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
109
|
/**
|
|
109
110
|
* Checks if the string represent a valid HH:mm:ss time.
|
|
110
111
|
* @param {string} string
|
|
@@ -114,15 +115,6 @@ export function isTimeString(string) {
|
|
|
114
115
|
return /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/u.test(string)
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
/**
|
|
118
|
-
* @deprecated Prefer isTimeString()
|
|
119
|
-
* @param {string} string
|
|
120
|
-
* @returns {boolean}
|
|
121
|
-
*/
|
|
122
|
-
export function isTime(string) {
|
|
123
|
-
return isTimeString(string)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
118
|
/**
|
|
127
119
|
* Checks if a number is a Unix timestamp (i.e. in seconds).
|
|
128
120
|
* Would not validate timestamps set very far into the future.
|
package/src/time.test.js
CHANGED
|
@@ -9,9 +9,8 @@ import {
|
|
|
9
9
|
getStartOfWeek,
|
|
10
10
|
getTime,
|
|
11
11
|
getTimeRange,
|
|
12
|
-
|
|
12
|
+
getUnixTimestamp,
|
|
13
13
|
isDateString,
|
|
14
|
-
isTime,
|
|
15
14
|
isTimeString,
|
|
16
15
|
isUnixTimestamp,
|
|
17
16
|
today,
|
|
@@ -178,6 +177,26 @@ describe("getTime", () => {
|
|
|
178
177
|
})
|
|
179
178
|
})
|
|
180
179
|
|
|
180
|
+
describe("getUnixTimestamp", () => {
|
|
181
|
+
test("parses Zulu (UTC) timestamp", () => {
|
|
182
|
+
expect(getUnixTimestamp("2024-06-01T12:34:56Z")).toBe(1717245296)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
test("parses timestamp with positive offset", () => {
|
|
186
|
+
const expected = Date.UTC(2024, 5, 1, 10, 34, 56) / 1000 // 12:34:56+02:00 == 10:34:56Z
|
|
187
|
+
expect(getUnixTimestamp("2024-06-01T12:34:56+02:00")).toBe(expected)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test("floors fractional seconds", () => {
|
|
191
|
+
// 999ms floors down to the same second
|
|
192
|
+
expect(getUnixTimestamp("1970-01-01T00:00:00.999Z")).toBe(0)
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test("returns NaN for invalid date string", () => {
|
|
196
|
+
expect(Number.isNaN(getUnixTimestamp("not-a-date"))).toBe(true)
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
|
|
181
200
|
describe("today", () => {
|
|
182
201
|
test("returns today's date in YYYY-MM-DD format", () => {
|
|
183
202
|
const expected = getTime().date
|
|
@@ -247,38 +266,6 @@ describe("isDateString", () => {
|
|
|
247
266
|
})
|
|
248
267
|
})
|
|
249
268
|
|
|
250
|
-
describe("isDate (deprecated wrapper)", () => {
|
|
251
|
-
test("returns true for valid YYYY-MM-DD dates", () => {
|
|
252
|
-
expect(isDate("2024-06-01")).toBe(true)
|
|
253
|
-
expect(isDate("1999-12-31")).toBe(true)
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
test("returns false for invalid dates (e.g., 2024-02-31)", () => {
|
|
257
|
-
expect(isDate("2024-02-31")).toBe(false)
|
|
258
|
-
expect(isDate("2023-04-31")).toBe(false)
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
test("returns false for invalid formats", () => {
|
|
262
|
-
expect(isDate("2024/06/01")).toBe(false)
|
|
263
|
-
expect(isDate("06-01-2024")).toBe(false)
|
|
264
|
-
expect(isDate("2024-6-1")).toBe(false)
|
|
265
|
-
expect(isDate("20240601")).toBe(false)
|
|
266
|
-
expect(isDate("abcd-ef-gh")).toBe(false)
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
test("returns false for impossible months and days", () => {
|
|
270
|
-
expect(isDate("2024-00-10")).toBe(false)
|
|
271
|
-
expect(isDate("2024-13-10")).toBe(false)
|
|
272
|
-
expect(isDate("2024-01-00")).toBe(false)
|
|
273
|
-
expect(isDate("2024-01-32")).toBe(false)
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
test("returns true for leap day", () => {
|
|
277
|
-
expect(isDate("2024-02-29")).toBe(true)
|
|
278
|
-
expect(isDate("2023-02-29")).toBe(false)
|
|
279
|
-
})
|
|
280
|
-
})
|
|
281
|
-
|
|
282
269
|
describe("isTimeString", () => {
|
|
283
270
|
test("validates correct times", () => {
|
|
284
271
|
expect(isTimeString("00:00:00")).toBe(true)
|
|
@@ -291,26 +278,6 @@ describe("isTimeString", () => {
|
|
|
291
278
|
})
|
|
292
279
|
})
|
|
293
280
|
|
|
294
|
-
describe("isTime (deprecated wrapper)", () => {
|
|
295
|
-
test("returns true for valid HH:mm:ss times", () => {
|
|
296
|
-
expect(isTime("00:00:00")).toBe(true)
|
|
297
|
-
expect(isTime("23:59:59")).toBe(true)
|
|
298
|
-
expect(isTime("12:34:56")).toBe(true)
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
test("returns false for invalid times", () => {
|
|
302
|
-
expect(isTime("24:00:00")).toBe(false)
|
|
303
|
-
expect(isTime("12:60:00")).toBe(false)
|
|
304
|
-
expect(isTime("12:00:60")).toBe(false)
|
|
305
|
-
expect(isTime("1:00:00")).toBe(false)
|
|
306
|
-
expect(isTime("12:0:00")).toBe(false)
|
|
307
|
-
expect(isTime("12:00:0")).toBe(false)
|
|
308
|
-
expect(isTime("12:00")).toBe(false)
|
|
309
|
-
expect(isTime("120000")).toBe(false)
|
|
310
|
-
expect(isTime("ab:cd:ef")).toBe(false)
|
|
311
|
-
})
|
|
312
|
-
})
|
|
313
|
-
|
|
314
281
|
describe("isUnixTimestamp", () => {
|
|
315
282
|
test("returns true for valid unix timestamps in seconds", () => {
|
|
316
283
|
expect(isUnixTimestamp(0)).toBe(true)
|
|
@@ -428,6 +395,14 @@ describe("getTimeRange", () => {
|
|
|
428
395
|
test("handles input with no seconds", () => {
|
|
429
396
|
expect(getTimeRange("12:00", "12:02")).toEqual(["12:00:00", "12:01:00", "12:02:00"])
|
|
430
397
|
})
|
|
398
|
+
|
|
399
|
+
// ISSUE: getTimeRange allows a zero step, which would otherwise loop forever; it's capped internally at 1440 iterations.
|
|
400
|
+
test("caps the number of results at MINUTES_IN_DAY when step is zero", () => {
|
|
401
|
+
const result = getTimeRange("12:00:00", "12:00:00", { hours: 0, minutes: 0 })
|
|
402
|
+
expect(result.length).toBe(24 * 60)
|
|
403
|
+
expect(result[0]).toBe("12:00:00")
|
|
404
|
+
expect(result[result.length - 1]).toBe("12:00:00")
|
|
405
|
+
})
|
|
431
406
|
})
|
|
432
407
|
|
|
433
408
|
describe("addDays", () => {
|