@synnaxlabs/x 0.55.0 → 0.56.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.
- package/.turbo/turbo-build.log +10 -13
- package/dist/src/array/nullable.d.ts +1 -1
- package/dist/src/array/nullable.d.ts.map +1 -1
- package/dist/src/caseconv/caseconv.d.ts.map +1 -1
- package/dist/src/compare/compare.d.ts +14 -0
- package/dist/src/compare/compare.d.ts.map +1 -1
- package/dist/src/debounce/debounce.d.ts +7 -2
- package/dist/src/debounce/debounce.d.ts.map +1 -1
- package/dist/src/destructor/destructor.d.ts +1 -0
- package/dist/src/destructor/destructor.d.ts.map +1 -1
- package/dist/src/errors/errors.d.ts +6 -10
- package/dist/src/errors/errors.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/notation/external.d.ts +3 -0
- package/dist/src/notation/external.d.ts.map +1 -0
- package/dist/src/notation/index.d.ts +1 -1
- package/dist/src/notation/notation.d.ts +5 -9
- package/dist/src/notation/notation.d.ts.map +1 -1
- package/dist/src/notation/types.gen.d.ts +9 -0
- package/dist/src/notation/types.gen.d.ts.map +1 -0
- package/dist/src/primitive/primitive.d.ts +16 -0
- package/dist/src/primitive/primitive.d.ts.map +1 -1
- package/dist/src/record/record.d.ts +8 -1
- package/dist/src/record/record.d.ts.map +1 -1
- package/dist/src/require/index.d.ts +2 -0
- package/dist/src/require/index.d.ts.map +1 -0
- package/dist/src/require/require.d.ts +2 -0
- package/dist/src/require/require.d.ts.map +1 -0
- package/dist/src/spatial/base.d.ts +1 -103
- package/dist/src/spatial/base.d.ts.map +1 -1
- package/dist/src/spatial/bounds/bounds.d.ts +3 -3
- package/dist/src/spatial/bounds/bounds.d.ts.map +1 -1
- package/dist/src/spatial/box/box.d.ts +7 -13
- package/dist/src/spatial/box/box.d.ts.map +1 -1
- package/dist/src/spatial/direction/direction.d.ts +17 -16
- package/dist/src/spatial/direction/direction.d.ts.map +1 -1
- package/dist/src/spatial/external.d.ts +1 -2
- package/dist/src/spatial/external.d.ts.map +1 -1
- package/dist/src/spatial/location/location.d.ts +28 -28
- package/dist/src/spatial/location/location.d.ts.map +1 -1
- package/dist/src/spatial/scale/scale.d.ts +2 -2
- package/dist/src/spatial/scale/scale.d.ts.map +1 -1
- package/dist/src/spatial/sticky/sticky.d.ts +15 -15
- package/dist/src/spatial/sticky/sticky.d.ts.map +1 -1
- package/dist/src/spatial/types.gen.d.ts +179 -2
- package/dist/src/spatial/types.gen.d.ts.map +1 -1
- package/dist/src/spatial/xy/xy.d.ts +4 -4
- package/dist/src/spatial/xy/xy.d.ts.map +1 -1
- package/dist/src/status/status.d.ts +11 -0
- package/dist/src/status/status.d.ts.map +1 -1
- package/dist/src/telem/external.d.ts +1 -0
- package/dist/src/telem/external.d.ts.map +1 -1
- package/dist/src/telem/series.d.ts +5 -2
- package/dist/src/telem/series.d.ts.map +1 -1
- package/dist/src/telem/telem.d.ts +42 -34
- package/dist/src/telem/telem.d.ts.map +1 -1
- package/dist/src/telem/types.gen.d.ts +19 -0
- package/dist/src/telem/types.gen.d.ts.map +1 -0
- package/dist/src/text/external.d.ts +3 -0
- package/dist/src/text/external.d.ts.map +1 -0
- package/dist/src/text/index.d.ts +2 -0
- package/dist/src/text/index.d.ts.map +1 -0
- package/dist/src/text/types.d.ts +21 -0
- package/dist/src/text/types.d.ts.map +1 -0
- package/dist/src/text/types.gen.d.ts +13 -0
- package/dist/src/text/types.gen.d.ts.map +1 -0
- package/dist/src/throttle/index.d.ts +2 -0
- package/dist/src/throttle/index.d.ts.map +1 -0
- package/dist/src/throttle/throttle.d.ts +3 -0
- package/dist/src/throttle/throttle.d.ts.map +1 -0
- package/dist/src/throttle/throttle.spec.d.ts +2 -0
- package/dist/src/throttle/throttle.spec.d.ts.map +1 -0
- package/dist/src/zod/parse.d.ts.map +1 -1
- package/dist/x.cjs +9 -9
- package/dist/x.js +1469 -1346
- package/package.json +11 -11
- package/src/array/nullable.ts +1 -4
- package/src/caseconv/caseconv.spec.ts +71 -0
- package/src/caseconv/caseconv.ts +15 -2
- package/src/compare/compare.spec.ts +115 -0
- package/src/compare/compare.ts +29 -0
- package/src/debounce/debounce.spec.ts +258 -24
- package/src/debounce/debounce.ts +49 -30
- package/src/deep/copy.spec.ts +13 -0
- package/src/deep/difference.ts +1 -1
- package/src/destructor/destructor.ts +2 -0
- package/src/errors/errors.spec.ts +30 -0
- package/src/errors/errors.ts +29 -17
- package/src/index.ts +4 -1
- package/src/notation/external.ts +11 -0
- package/src/notation/index.ts +1 -1
- package/src/notation/notation.spec.ts +260 -2
- package/src/notation/notation.ts +25 -7
- package/src/notation/types.gen.ts +16 -0
- package/src/primitive/primitive.spec.ts +58 -5
- package/src/primitive/primitive.ts +22 -0
- package/src/record/record.spec.ts +26 -0
- package/src/record/record.ts +20 -5
- package/src/require/index.ts +10 -0
- package/src/require/require.ts +10 -0
- package/src/spatial/base.ts +1 -93
- package/src/spatial/bounds/bounds.ts +10 -10
- package/src/spatial/box/box.ts +5 -5
- package/src/spatial/direction/direction.ts +16 -17
- package/src/spatial/external.ts +1 -2
- package/src/spatial/location/location.ts +19 -17
- package/src/spatial/scale/scale.ts +2 -2
- package/src/spatial/sticky/sticky.spec.ts +2 -2
- package/src/spatial/sticky/sticky.ts +6 -13
- package/src/spatial/types.gen.ts +140 -0
- package/src/spatial/xy/xy.ts +7 -7
- package/src/status/status.spec.ts +65 -0
- package/src/status/status.ts +20 -0
- package/src/telem/external.ts +8 -0
- package/src/telem/series.spec.ts +183 -0
- package/src/telem/series.ts +54 -16
- package/src/telem/telem.spec.ts +128 -9
- package/src/telem/telem.ts +91 -79
- package/src/telem/types.gen.ts +28 -0
- package/src/text/external.ts +11 -0
- package/src/text/index.ts +10 -0
- package/src/text/types.gen.ts +16 -0
- package/src/text/types.ts +37 -0
- package/src/{worker → throttle}/index.ts +1 -1
- package/src/throttle/throttle.spec.ts +147 -0
- package/src/throttle/throttle.ts +44 -0
- package/src/zod/parse.ts +2 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/src/spatial/spatial.d.ts +0 -3
- package/dist/src/spatial/spatial.d.ts.map +0 -1
- package/dist/src/worker/index.d.ts +0 -2
- package/dist/src/worker/index.d.ts.map +0 -1
- package/dist/src/worker/worker.d.ts +0 -33
- package/dist/src/worker/worker.d.ts.map +0 -1
- package/dist/src/worker/worker.spec.d.ts +0 -2
- package/dist/src/worker/worker.spec.d.ts.map +0 -1
- package/src/spatial/spatial.ts +0 -44
- package/src/worker/worker.spec.ts +0 -41
- package/src/worker/worker.ts +0 -86
package/src/telem/telem.spec.ts
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
import { afterEach, beforeEach, describe, expect, it, test } from "vitest";
|
|
11
11
|
|
|
12
12
|
import { binary } from "@/binary";
|
|
13
|
+
import { primitive } from "@/primitive";
|
|
13
14
|
import {
|
|
15
|
+
convertDataType,
|
|
14
16
|
type CrudeDataType,
|
|
15
17
|
DataType,
|
|
16
18
|
Density,
|
|
@@ -19,7 +21,7 @@ import {
|
|
|
19
21
|
TimeRange,
|
|
20
22
|
TimeSpan,
|
|
21
23
|
TimeStamp,
|
|
22
|
-
type
|
|
24
|
+
type TimestampFormat,
|
|
23
25
|
} from "@/telem";
|
|
24
26
|
|
|
25
27
|
describe("TimeStamp", () => {
|
|
@@ -136,7 +138,7 @@ describe("TimeStamp", () => {
|
|
|
136
138
|
expect(ts.millisecond).toBe(0);
|
|
137
139
|
});
|
|
138
140
|
|
|
139
|
-
test("should round-trip when using local
|
|
141
|
+
test("should round-trip when using local TimeZone", () => {
|
|
140
142
|
const input = "2025-11-03T17:44:45.809";
|
|
141
143
|
const ts1 = new TimeStamp(input, "local");
|
|
142
144
|
const output = ts1.toString("ISO", "local").slice(0, -1);
|
|
@@ -539,10 +541,9 @@ describe("TimeStamp", () => {
|
|
|
539
541
|
.add(TimeSpan.minutes(20))
|
|
540
542
|
.add(TimeSpan.milliseconds(12));
|
|
541
543
|
|
|
542
|
-
const FORMAT_TESTS: [
|
|
544
|
+
const FORMAT_TESTS: [TimestampFormat, string][] = [
|
|
543
545
|
["ISO", "2022-12-15T12:20:00.012Z"],
|
|
544
546
|
["ISODate", "2022-12-15"],
|
|
545
|
-
["ISOTime", "12:20:00.012"],
|
|
546
547
|
["time", "12:20:00"],
|
|
547
548
|
["preciseTime", "12:20:00.012"],
|
|
548
549
|
["date", "Dec 15"],
|
|
@@ -920,10 +921,10 @@ describe("TimeStamp", () => {
|
|
|
920
921
|
});
|
|
921
922
|
|
|
922
923
|
describe("formatBySpan", () => {
|
|
923
|
-
test("should return '
|
|
924
|
+
test("should return 'date' for spans >= 30 days", () => {
|
|
924
925
|
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
925
926
|
const span = TimeSpan.days(30);
|
|
926
|
-
expect(ts.formatBySpan(span)).toBe("
|
|
927
|
+
expect(ts.formatBySpan(span)).toBe("date");
|
|
927
928
|
});
|
|
928
929
|
|
|
929
930
|
test("should return 'dateTime' for spans >= 1 day", () => {
|
|
@@ -944,16 +945,34 @@ describe("TimeStamp", () => {
|
|
|
944
945
|
expect(ts.formatBySpan(span)).toBe("preciseTime");
|
|
945
946
|
});
|
|
946
947
|
|
|
947
|
-
test("should return '
|
|
948
|
+
test("should return 'preciseTime' for spans < 1 second", () => {
|
|
948
949
|
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
949
950
|
const span = TimeSpan.milliseconds(500);
|
|
950
|
-
expect(ts.formatBySpan(span)).toBe("
|
|
951
|
+
expect(ts.formatBySpan(span)).toBe("preciseTime");
|
|
951
952
|
});
|
|
952
953
|
|
|
953
954
|
test("should work with very small spans", () => {
|
|
954
955
|
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
955
956
|
const span = TimeSpan.microseconds(100);
|
|
956
|
-
expect(ts.formatBySpan(span)).toBe("
|
|
957
|
+
expect(ts.formatBySpan(span)).toBe("preciseTime");
|
|
958
|
+
});
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
describe("hash", () => {
|
|
962
|
+
it("returns the bigint nanosecond value as a string", () => {
|
|
963
|
+
expect(new TimeStamp(1234567890n).hash()).toBe("1234567890");
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
it("is stable across instances representing the same value", () => {
|
|
967
|
+
expect(new TimeStamp(42n).hash()).toBe(new TimeStamp(42n).hash());
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
it("differs across distinct values", () => {
|
|
971
|
+
expect(new TimeStamp(1n).hash()).not.toBe(new TimeStamp(2n).hash());
|
|
972
|
+
});
|
|
973
|
+
|
|
974
|
+
it("satisfies primitive.isHashable", () => {
|
|
975
|
+
expect(primitive.isHashable(new TimeStamp(0n))).toBe(true);
|
|
957
976
|
});
|
|
958
977
|
});
|
|
959
978
|
});
|
|
@@ -1358,6 +1377,20 @@ describe("TimeSpan", () => {
|
|
|
1358
1377
|
expect(ts2.valueOf()).toBe(BigInt(Number.MAX_SAFE_INTEGER));
|
|
1359
1378
|
});
|
|
1360
1379
|
});
|
|
1380
|
+
|
|
1381
|
+
describe("hash", () => {
|
|
1382
|
+
it("returns the bigint nanosecond value as a string", () => {
|
|
1383
|
+
expect(TimeSpan.milliseconds(500).hash()).toBe("500000000");
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
it("is stable across instances representing the same value", () => {
|
|
1387
|
+
expect(TimeSpan.seconds(1).hash()).toBe(TimeSpan.seconds(1).hash());
|
|
1388
|
+
});
|
|
1389
|
+
|
|
1390
|
+
it("satisfies primitive.isHashable", () => {
|
|
1391
|
+
expect(primitive.isHashable(TimeSpan.ZERO)).toBe(true);
|
|
1392
|
+
});
|
|
1393
|
+
});
|
|
1361
1394
|
});
|
|
1362
1395
|
|
|
1363
1396
|
describe("Rate", () => {
|
|
@@ -1474,6 +1507,20 @@ describe("Rate", () => {
|
|
|
1474
1507
|
expect(result.valueOf()).toBe(200);
|
|
1475
1508
|
});
|
|
1476
1509
|
});
|
|
1510
|
+
|
|
1511
|
+
describe("hash", () => {
|
|
1512
|
+
it("returns the Hz value as a string", () => {
|
|
1513
|
+
expect(new Rate(100).hash()).toBe("100");
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
it("is stable across instances representing the same value", () => {
|
|
1517
|
+
expect(new Rate(60).hash()).toBe(new Rate(60).hash());
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
it("satisfies primitive.isHashable", () => {
|
|
1521
|
+
expect(primitive.isHashable(new Rate(1))).toBe(true);
|
|
1522
|
+
});
|
|
1523
|
+
});
|
|
1477
1524
|
});
|
|
1478
1525
|
|
|
1479
1526
|
describe("TimeRange", () => {
|
|
@@ -1751,6 +1798,33 @@ describe("TimeRange", () => {
|
|
|
1751
1798
|
});
|
|
1752
1799
|
});
|
|
1753
1800
|
});
|
|
1801
|
+
|
|
1802
|
+
describe("hash", () => {
|
|
1803
|
+
it("composes the start and end hashes with a dash", () => {
|
|
1804
|
+
const tr = new TimeRange(new TimeStamp(100n), new TimeStamp(200n));
|
|
1805
|
+
expect(tr.hash()).toBe("100-200");
|
|
1806
|
+
});
|
|
1807
|
+
|
|
1808
|
+
it("is stable across instances representing the same range", () => {
|
|
1809
|
+
const a = new TimeRange(new TimeStamp(1n), new TimeStamp(2n));
|
|
1810
|
+
const b = new TimeRange(new TimeStamp(1n), new TimeStamp(2n));
|
|
1811
|
+
expect(a.hash()).toBe(b.hash());
|
|
1812
|
+
});
|
|
1813
|
+
|
|
1814
|
+
it("differs when start or end differs", () => {
|
|
1815
|
+
const base = new TimeRange(new TimeStamp(1n), new TimeStamp(2n));
|
|
1816
|
+
expect(base.hash()).not.toBe(
|
|
1817
|
+
new TimeRange(new TimeStamp(1n), new TimeStamp(3n)).hash(),
|
|
1818
|
+
);
|
|
1819
|
+
expect(base.hash()).not.toBe(
|
|
1820
|
+
new TimeRange(new TimeStamp(0n), new TimeStamp(2n)).hash(),
|
|
1821
|
+
);
|
|
1822
|
+
});
|
|
1823
|
+
|
|
1824
|
+
it("satisfies primitive.isHashable", () => {
|
|
1825
|
+
expect(primitive.isHashable(TimeRange.ZERO)).toBe(true);
|
|
1826
|
+
});
|
|
1827
|
+
});
|
|
1754
1828
|
});
|
|
1755
1829
|
|
|
1756
1830
|
describe("Density", () => {
|
|
@@ -2022,6 +2096,25 @@ describe("DataType", () => {
|
|
|
2022
2096
|
});
|
|
2023
2097
|
});
|
|
2024
2098
|
});
|
|
2099
|
+
|
|
2100
|
+
describe("hash", () => {
|
|
2101
|
+
it("returns the data type identifier as a string", () => {
|
|
2102
|
+
expect(DataType.FLOAT32.hash()).toBe("float32");
|
|
2103
|
+
expect(DataType.STRING.hash()).toBe("string");
|
|
2104
|
+
});
|
|
2105
|
+
|
|
2106
|
+
it("is stable across instances representing the same data type", () => {
|
|
2107
|
+
expect(new DataType("uint8").hash()).toBe(new DataType("uint8").hash());
|
|
2108
|
+
});
|
|
2109
|
+
|
|
2110
|
+
it("differs across distinct data types", () => {
|
|
2111
|
+
expect(DataType.FLOAT32.hash()).not.toBe(DataType.FLOAT64.hash());
|
|
2112
|
+
});
|
|
2113
|
+
|
|
2114
|
+
it("satisfies primitive.isHashable", () => {
|
|
2115
|
+
expect(primitive.isHashable(DataType.UNKNOWN)).toBe(true);
|
|
2116
|
+
});
|
|
2117
|
+
});
|
|
2025
2118
|
});
|
|
2026
2119
|
|
|
2027
2120
|
describe("Size", () => {
|
|
@@ -2163,3 +2256,29 @@ describe("Size", () => {
|
|
|
2163
2256
|
});
|
|
2164
2257
|
});
|
|
2165
2258
|
});
|
|
2259
|
+
|
|
2260
|
+
describe("convertDataType", () => {
|
|
2261
|
+
it("preserves precision when subtracting a bigint offset above 2^53 (INT64 -> FLOAT32)", () => {
|
|
2262
|
+
const offset = 1778020940471336960n;
|
|
2263
|
+
const value = 1778020940471336960n + 137438953472n;
|
|
2264
|
+
const result = convertDataType(DataType.INT64, DataType.FLOAT32, value, offset);
|
|
2265
|
+
expect(result).toBe(137438953472);
|
|
2266
|
+
});
|
|
2267
|
+
|
|
2268
|
+
it("preserves precision when subtracting a bigint offset above 2^53 (TIMESTAMP -> FLOAT32)", () => {
|
|
2269
|
+
const offset = 1778020940471336960n;
|
|
2270
|
+
const value = 1778020940471336960n + 1n;
|
|
2271
|
+
const result = convertDataType(DataType.TIMESTAMP, DataType.FLOAT32, value, offset);
|
|
2272
|
+
expect(result).toBe(1);
|
|
2273
|
+
});
|
|
2274
|
+
|
|
2275
|
+
it("returns a bigint when target uses bigint and source does not", () => {
|
|
2276
|
+
const result = convertDataType(DataType.FLOAT32, DataType.INT64, 100, 10);
|
|
2277
|
+
expect(result).toBe(90n);
|
|
2278
|
+
});
|
|
2279
|
+
|
|
2280
|
+
it("falls back to math.sub when neither source nor target use bigint", () => {
|
|
2281
|
+
const result = convertDataType(DataType.FLOAT32, DataType.FLOAT64, 5.5, 1.5);
|
|
2282
|
+
expect(result).toBe(4);
|
|
2283
|
+
});
|
|
2284
|
+
});
|
package/src/telem/telem.ts
CHANGED
|
@@ -12,25 +12,11 @@ import { z } from "zod";
|
|
|
12
12
|
import { math } from "@/math";
|
|
13
13
|
import { primitive } from "@/primitive";
|
|
14
14
|
import { type bounds } from "@/spatial";
|
|
15
|
-
|
|
16
|
-
/** Time zone specification when working with time stamps. */
|
|
17
|
-
export type TZInfo = "UTC" | "local";
|
|
15
|
+
import { type TimestampFormat, type TimeZone } from "@/telem/types.gen";
|
|
18
16
|
|
|
19
17
|
const SIMPLE_DAYS_IN_YEAR = 365;
|
|
20
18
|
const SIMPLE_DAYS_IN_MONTH = 30;
|
|
21
19
|
|
|
22
|
-
/** Different string formats for time stamps. */
|
|
23
|
-
export type TimeStampStringFormat =
|
|
24
|
-
| "ISO"
|
|
25
|
-
| "ISODate"
|
|
26
|
-
| "ISOTime"
|
|
27
|
-
| "time"
|
|
28
|
-
| "preciseTime"
|
|
29
|
-
| "date"
|
|
30
|
-
| "preciseDate"
|
|
31
|
-
| "shortDate"
|
|
32
|
-
| "dateTime";
|
|
33
|
-
|
|
34
20
|
/** Different string formats for time spans. */
|
|
35
21
|
export type TimeSpanStringFormat = "full" | "semantic";
|
|
36
22
|
|
|
@@ -79,35 +65,42 @@ UTC timestamp. Synnax uses a nanosecond precision int64 timestamp.
|
|
|
79
65
|
*
|
|
80
66
|
* 1. A number representing the number of nanoseconds since the Unix epoch.
|
|
81
67
|
* 2. A JavaScript Date object.
|
|
82
|
-
* 3. An array of numbers satisfying the DateComponents type, where the first element is
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
68
|
+
* 3. An array of numbers satisfying the DateComponents type, where the first element is
|
|
69
|
+
* the year, the second is the month, and the third is the day. To increase
|
|
70
|
+
* resolution when using this method, use the add method. It's important to note that
|
|
71
|
+
* this initializes a timestamp at midnight UTC, regardless of the TimeZone
|
|
72
|
+
* specified.
|
|
73
|
+
* 4. An ISO compliant date or date time string. The TimeZone component is ignored.
|
|
87
74
|
*
|
|
88
|
-
* @param
|
|
89
|
-
* "local". This parameter is ignored if the value is a Date object or a
|
|
75
|
+
* @param timeZone - The TimeZone to use when parsing the TimeStamp. This can be either
|
|
76
|
+
* "UTC" or "local". This parameter is ignored if the value is a Date object or a
|
|
77
|
+
* DateComponents array.
|
|
90
78
|
*
|
|
91
79
|
* @example ts = new TimeStamp(1 * TimeSpan.HOUR) // 1 hour after the Unix epoch
|
|
92
|
-
* @example ts = new TimeStamp([2021, 1, 1]) // 1/1/2021
|
|
93
|
-
* @example ts = new TimeStamp([2021, 1, 1]).add(1 * TimeSpan.HOUR) // 1/1/2021
|
|
94
|
-
* @example ts = new TimeStamp("2021-01-01T12:30:00Z") // 1/1/2021
|
|
80
|
+
* @example ts = new TimeStamp([2021, 1, 1]) // 1/1/2021 midnight UTC
|
|
81
|
+
* @example ts = new TimeStamp([2021, 1, 1]).add(1 * TimeSpan.HOUR) // 1/1/2021 1am UTC
|
|
82
|
+
* @example ts = new TimeStamp("2021-01-01T12:30:00Z") // 1/1/2021 12:30pm UTC
|
|
95
83
|
*/
|
|
96
84
|
export class TimeStamp
|
|
97
85
|
extends primitive.ValueExtension<bigint>
|
|
98
|
-
implements primitive.Stringer
|
|
86
|
+
implements primitive.Stringer, primitive.Hashable
|
|
99
87
|
{
|
|
100
|
-
|
|
88
|
+
/** @returns the bigint nanosecond value as a string for stable hashing. */
|
|
89
|
+
hash(): string {
|
|
90
|
+
return this.value.toString();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
constructor(value?: CrudeTimeStamp, timeZone: TimeZone = "UTC") {
|
|
101
94
|
if (value == null) super(TimeStamp.now().valueOf());
|
|
102
95
|
else if (value instanceof Date)
|
|
103
96
|
super(BigInt(value.getTime()) * TimeStamp.MILLISECOND.valueOf());
|
|
104
97
|
else if (typeof value === "string")
|
|
105
|
-
super(TimeStamp.parseDateTimeString(value,
|
|
98
|
+
super(TimeStamp.parseDateTimeString(value, timeZone).valueOf());
|
|
106
99
|
else if (Array.isArray(value)) super(TimeStamp.parseDate(value));
|
|
107
100
|
else {
|
|
108
101
|
let offset = 0n;
|
|
109
102
|
if (value instanceof Number) value = value.valueOf();
|
|
110
|
-
if (
|
|
103
|
+
if (timeZone === "local") offset = TimeStamp.utcOffset.valueOf();
|
|
111
104
|
if (typeof value === "number")
|
|
112
105
|
if (isFinite(value))
|
|
113
106
|
if (value === math.MAX_INT64_NUMBER) value = math.MAX_INT64;
|
|
@@ -138,7 +131,7 @@ export class TimeStamp
|
|
|
138
131
|
return this.value;
|
|
139
132
|
}
|
|
140
133
|
|
|
141
|
-
private static parseTimeString(time: string,
|
|
134
|
+
private static parseTimeString(time: string, timeZone: TimeZone = "UTC"): bigint {
|
|
142
135
|
const [hours, minutes, mbeSeconds] = time.split(":");
|
|
143
136
|
let seconds = "00";
|
|
144
137
|
let milliseconds: string | undefined = "00";
|
|
@@ -147,13 +140,13 @@ export class TimeStamp
|
|
|
147
140
|
.add(TimeStamp.minutes(parseInt(minutes ?? "00", 10)))
|
|
148
141
|
.add(TimeStamp.seconds(parseInt(seconds ?? "00", 10)))
|
|
149
142
|
.add(TimeStamp.milliseconds(parseInt(milliseconds ?? "00", 10)));
|
|
150
|
-
if (
|
|
143
|
+
if (timeZone === "local") base = base.add(TimeStamp.utcOffset);
|
|
151
144
|
return base.valueOf();
|
|
152
145
|
}
|
|
153
146
|
|
|
154
|
-
private static parseDateTimeString(str: string,
|
|
147
|
+
private static parseDateTimeString(str: string, timeZone: TimeZone = "UTC"): bigint {
|
|
155
148
|
if (!str.includes("/") && !str.includes("-"))
|
|
156
|
-
return TimeStamp.parseTimeString(str,
|
|
149
|
+
return TimeStamp.parseTimeString(str, timeZone);
|
|
157
150
|
|
|
158
151
|
const isDateTimeLocal =
|
|
159
152
|
str.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?$/) != null;
|
|
@@ -170,7 +163,7 @@ export class TimeStamp
|
|
|
170
163
|
}
|
|
171
164
|
|
|
172
165
|
const d =
|
|
173
|
-
|
|
166
|
+
timeZone === "local"
|
|
174
167
|
? new Date(datePart.replace("T", " "))
|
|
175
168
|
: new Date(`${datePart}Z`);
|
|
176
169
|
|
|
@@ -181,17 +174,17 @@ export class TimeStamp
|
|
|
181
174
|
}
|
|
182
175
|
|
|
183
176
|
const d = new Date(str);
|
|
184
|
-
// Essential to note that this makes the date midnight in UTC! Not local!
|
|
185
|
-
//
|
|
177
|
+
// Essential to note that this makes the date midnight in UTC! Not local! As a
|
|
178
|
+
// result, we need to add the timeZone offset back in.
|
|
186
179
|
if (!str.includes(":")) d.setUTCHours(0, 0, 0, 0);
|
|
187
180
|
return new TimeStamp(
|
|
188
181
|
BigInt(d.getTime()) * TimeStamp.MILLISECOND.valueOf(),
|
|
189
|
-
|
|
182
|
+
timeZone,
|
|
190
183
|
).valueOf();
|
|
191
184
|
}
|
|
192
185
|
|
|
193
|
-
private toISOString(
|
|
194
|
-
if (
|
|
186
|
+
private toISOString(timeZone: TimeZone = "UTC"): string {
|
|
187
|
+
if (timeZone === "UTC") return this.date().toISOString();
|
|
195
188
|
const d = this.date();
|
|
196
189
|
const offset = new TimeSpan(
|
|
197
190
|
BigInt(d.getTimezoneOffset()) * TimeStamp.MINUTE.valueOf(),
|
|
@@ -199,8 +192,11 @@ export class TimeStamp
|
|
|
199
192
|
return this.sub(offset).date().toISOString();
|
|
200
193
|
}
|
|
201
194
|
|
|
202
|
-
private timeString(
|
|
203
|
-
|
|
195
|
+
private timeString(
|
|
196
|
+
milliseconds: boolean = false,
|
|
197
|
+
timeZone: TimeZone = "UTC",
|
|
198
|
+
): string {
|
|
199
|
+
const iso = this.toISOString(timeZone);
|
|
204
200
|
return milliseconds ? iso.slice(11, 23) : iso.slice(11, 19);
|
|
205
201
|
}
|
|
206
202
|
|
|
@@ -639,27 +635,25 @@ export class TimeStamp
|
|
|
639
635
|
* Returns a string representation of the TimeStamp.
|
|
640
636
|
*
|
|
641
637
|
* @param format - Optional format for the string representation. Defaults to "ISO".
|
|
642
|
-
* @param
|
|
638
|
+
* @param timeZone - Optional TimeZone. Defaults to "UTC".
|
|
643
639
|
* @returns A string representation of the TimeStamp.
|
|
644
640
|
*/
|
|
645
|
-
toString(format:
|
|
641
|
+
toString(format: TimestampFormat = "ISO", timeZone: TimeZone = "UTC"): string {
|
|
646
642
|
switch (format) {
|
|
647
643
|
case "ISODate":
|
|
648
|
-
return this.toISOString(
|
|
649
|
-
case "ISOTime":
|
|
650
|
-
return this.toISOString(tzInfo).slice(11, 23);
|
|
644
|
+
return this.toISOString(timeZone).slice(0, 10);
|
|
651
645
|
case "time":
|
|
652
|
-
return this.timeString(false,
|
|
646
|
+
return this.timeString(false, timeZone);
|
|
653
647
|
case "preciseTime":
|
|
654
|
-
return this.timeString(true,
|
|
648
|
+
return this.timeString(true, timeZone);
|
|
655
649
|
case "date":
|
|
656
650
|
return this.dateString();
|
|
657
651
|
case "preciseDate":
|
|
658
|
-
return `${this.dateString()} ${this.timeString(true,
|
|
652
|
+
return `${this.dateString()} ${this.timeString(true, timeZone)}`;
|
|
659
653
|
case "dateTime":
|
|
660
|
-
return `${this.dateString()} ${this.timeString(false,
|
|
654
|
+
return `${this.dateString()} ${this.timeString(false, timeZone)}`;
|
|
661
655
|
default:
|
|
662
|
-
return this.toISOString(
|
|
656
|
+
return this.toISOString(timeZone);
|
|
663
657
|
}
|
|
664
658
|
}
|
|
665
659
|
|
|
@@ -697,22 +691,19 @@ export class TimeStamp
|
|
|
697
691
|
* Determines the appropriate string format based on the span magnitude.
|
|
698
692
|
*
|
|
699
693
|
* @param span - The span that provides context for format selection
|
|
700
|
-
* @returns The appropriate
|
|
694
|
+
* @returns The appropriate TimestampFormat
|
|
701
695
|
*
|
|
702
696
|
* Rules:
|
|
703
|
-
* - For spans >= 30 days: "
|
|
697
|
+
* - For spans >= 30 days: "date" (e.g., "Nov 5")
|
|
704
698
|
* - For spans >= 1 day: "dateTime" (e.g., "Nov 5 14:23:45")
|
|
705
699
|
* - For spans >= 1 hour: "time" (e.g., "14:23:45")
|
|
706
|
-
* - For spans
|
|
707
|
-
* - For spans < 1 second: "ISOTime" (full precision time)
|
|
700
|
+
* - For spans < 1 hour: "preciseTime" (e.g., "14:23:45.123")
|
|
708
701
|
*/
|
|
709
|
-
formatBySpan(span: TimeSpan):
|
|
710
|
-
if (span.greaterThanOrEqual(TimeSpan.days(30))) return "
|
|
702
|
+
formatBySpan(span: TimeSpan): TimestampFormat {
|
|
703
|
+
if (span.greaterThanOrEqual(TimeSpan.days(30))) return "date";
|
|
711
704
|
if (span.greaterThanOrEqual(TimeSpan.DAY)) return "dateTime";
|
|
712
705
|
if (span.greaterThanOrEqual(TimeSpan.HOUR)) return "time";
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
return "ISOTime";
|
|
706
|
+
return "preciseTime";
|
|
716
707
|
}
|
|
717
708
|
|
|
718
709
|
/**
|
|
@@ -760,56 +751,56 @@ export class TimeStamp
|
|
|
760
751
|
* @param value - The number of nanoseconds.
|
|
761
752
|
* @returns A TimeStamp representing the given number of nanoseconds.
|
|
762
753
|
*/
|
|
763
|
-
static nanoseconds(value: number,
|
|
764
|
-
return new TimeStamp(value,
|
|
754
|
+
static nanoseconds(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
755
|
+
return new TimeStamp(value, timeZone);
|
|
765
756
|
}
|
|
766
757
|
|
|
767
758
|
/** One nanosecond after the unix epoch */
|
|
768
759
|
static readonly NANOSECOND = TimeStamp.nanoseconds(1);
|
|
769
760
|
|
|
770
761
|
/** @returns a new TimeStamp n microseconds after the unix epoch */
|
|
771
|
-
static microseconds(value: number,
|
|
772
|
-
return TimeStamp.nanoseconds(value * 1000,
|
|
762
|
+
static microseconds(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
763
|
+
return TimeStamp.nanoseconds(value * 1000, timeZone);
|
|
773
764
|
}
|
|
774
765
|
|
|
775
766
|
/** One microsecond after the unix epoch */
|
|
776
767
|
static readonly MICROSECOND = TimeStamp.microseconds(1);
|
|
777
768
|
|
|
778
769
|
/** @returns a new TimeStamp n milliseconds after the unix epoch */
|
|
779
|
-
static milliseconds(value: number,
|
|
780
|
-
return TimeStamp.microseconds(value * 1000,
|
|
770
|
+
static milliseconds(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
771
|
+
return TimeStamp.microseconds(value * 1000, timeZone);
|
|
781
772
|
}
|
|
782
773
|
|
|
783
774
|
/** One millisecond after the unix epoch */
|
|
784
775
|
static readonly MILLISECOND = TimeStamp.milliseconds(1);
|
|
785
776
|
|
|
786
777
|
/** @returns a new TimeStamp n seconds after the unix epoch */
|
|
787
|
-
static seconds(value: number,
|
|
788
|
-
return TimeStamp.milliseconds(value * 1000,
|
|
778
|
+
static seconds(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
779
|
+
return TimeStamp.milliseconds(value * 1000, timeZone);
|
|
789
780
|
}
|
|
790
781
|
|
|
791
782
|
/** One second after the unix epoch */
|
|
792
783
|
static readonly SECOND = TimeStamp.seconds(1);
|
|
793
784
|
|
|
794
785
|
/** @returns a new TimeStamp n minutes after the unix epoch */
|
|
795
|
-
static minutes(value: number,
|
|
796
|
-
return TimeStamp.seconds(value * 60,
|
|
786
|
+
static minutes(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
787
|
+
return TimeStamp.seconds(value * 60, timeZone);
|
|
797
788
|
}
|
|
798
789
|
|
|
799
790
|
/** One minute after the unix epoch */
|
|
800
791
|
static readonly MINUTE = TimeStamp.minutes(1);
|
|
801
792
|
|
|
802
793
|
/** @returns a new TimeStamp n hours after the unix epoch */
|
|
803
|
-
static hours(value: number,
|
|
804
|
-
return TimeStamp.minutes(value * 60,
|
|
794
|
+
static hours(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
795
|
+
return TimeStamp.minutes(value * 60, timeZone);
|
|
805
796
|
}
|
|
806
797
|
|
|
807
798
|
/** One hour after the unix epoch */
|
|
808
799
|
static readonly HOUR = TimeStamp.hours(1);
|
|
809
800
|
|
|
810
801
|
/** @returns a new TimeStamp n days after the unix epoch */
|
|
811
|
-
static days(value: number,
|
|
812
|
-
return TimeStamp.hours(value * 24,
|
|
802
|
+
static days(value: number, timeZone: TimeZone = "UTC"): TimeStamp {
|
|
803
|
+
return TimeStamp.hours(value * 24, timeZone);
|
|
813
804
|
}
|
|
814
805
|
|
|
815
806
|
/** One day after the unix epoch */
|
|
@@ -852,7 +843,7 @@ export class TimeStamp
|
|
|
852
843
|
/** TimeSpan represents a nanosecond precision duration. */
|
|
853
844
|
export class TimeSpan
|
|
854
845
|
extends primitive.ValueExtension<bigint>
|
|
855
|
-
implements primitive.Stringer
|
|
846
|
+
implements primitive.Stringer, primitive.Hashable
|
|
856
847
|
{
|
|
857
848
|
constructor(value: CrudeTimeSpan) {
|
|
858
849
|
if (typeof value === "number") value = Math.trunc(value.valueOf());
|
|
@@ -898,6 +889,11 @@ export class TimeSpan
|
|
|
898
889
|
return this.value;
|
|
899
890
|
}
|
|
900
891
|
|
|
892
|
+
/** @returns the bigint nanosecond value as a string for stable hashing. */
|
|
893
|
+
hash(): string {
|
|
894
|
+
return this.value.toString();
|
|
895
|
+
}
|
|
896
|
+
|
|
901
897
|
/**
|
|
902
898
|
* Checks if the TimeSpan is less than another TimeSpan.
|
|
903
899
|
*
|
|
@@ -1310,13 +1306,18 @@ export class TimeSpan
|
|
|
1310
1306
|
/** Rate represents a data rate in Hz. */
|
|
1311
1307
|
export class Rate
|
|
1312
1308
|
extends primitive.ValueExtension<number>
|
|
1313
|
-
implements primitive.Stringer
|
|
1309
|
+
implements primitive.Stringer, primitive.Hashable
|
|
1314
1310
|
{
|
|
1315
1311
|
constructor(value: CrudeRate) {
|
|
1316
1312
|
if (primitive.isCrudeValueExtension<number>(value)) value = value.value;
|
|
1317
1313
|
super(value.valueOf());
|
|
1318
1314
|
}
|
|
1319
1315
|
|
|
1316
|
+
/** @returns the Hz value as a string for stable hashing. */
|
|
1317
|
+
hash(): string {
|
|
1318
|
+
return this.value.toString();
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1320
1321
|
/** @returns a pretty string representation of the rate in the format "X Hz". */
|
|
1321
1322
|
toString(): string {
|
|
1322
1323
|
return `${this.valueOf()} Hz`;
|
|
@@ -1549,7 +1550,12 @@ export class Density
|
|
|
1549
1550
|
* @property start - A TimeStamp representing the start of the range.
|
|
1550
1551
|
* @property end - A Timestamp representing the end of the range.
|
|
1551
1552
|
*/
|
|
1552
|
-
export class TimeRange implements primitive.Stringer {
|
|
1553
|
+
export class TimeRange implements primitive.Stringer, primitive.Hashable {
|
|
1554
|
+
/** @returns a stable hash composed of the start and end timestamps. */
|
|
1555
|
+
hash(): string {
|
|
1556
|
+
return `${this.start.hash()}-${this.end.hash()}`;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1553
1559
|
/**
|
|
1554
1560
|
* The starting TimeStamp of the TimeRange.
|
|
1555
1561
|
*
|
|
@@ -1823,8 +1829,13 @@ export class TimeRange implements primitive.Stringer {
|
|
|
1823
1829
|
/** DataType is a string that represents a data type. */
|
|
1824
1830
|
export class DataType
|
|
1825
1831
|
extends primitive.ValueExtension<string>
|
|
1826
|
-
implements primitive.Stringer
|
|
1832
|
+
implements primitive.Stringer, primitive.Hashable
|
|
1827
1833
|
{
|
|
1834
|
+
/** @returns the data type identifier as a string for stable hashing. */
|
|
1835
|
+
hash(): string {
|
|
1836
|
+
return this.value;
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1828
1839
|
constructor(value: CrudeDataType) {
|
|
1829
1840
|
if (primitive.isCrudeValueExtension<string>(value)) value = value.value;
|
|
1830
1841
|
if (
|
|
@@ -2418,7 +2429,8 @@ export const convertDataType = (
|
|
|
2418
2429
|
value: math.Numeric,
|
|
2419
2430
|
offset: math.Numeric = 0,
|
|
2420
2431
|
): math.Numeric => {
|
|
2421
|
-
if (source.usesBigInt && !target.usesBigInt)
|
|
2432
|
+
if (source.usesBigInt && !target.usesBigInt)
|
|
2433
|
+
return Number(BigInt(value.valueOf()) - BigInt(offset.valueOf()));
|
|
2422
2434
|
if (!source.usesBigInt && target.usesBigInt)
|
|
2423
2435
|
return BigInt(value.valueOf()) - BigInt(offset.valueOf());
|
|
2424
2436
|
return math.sub(value, offset);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
// Code generated by Oracle. DO NOT EDIT.
|
|
11
|
+
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
export const TIMESTAMP_FORMATS = [
|
|
15
|
+
"ISO",
|
|
16
|
+
"ISODate",
|
|
17
|
+
"time",
|
|
18
|
+
"preciseTime",
|
|
19
|
+
"date",
|
|
20
|
+
"preciseDate",
|
|
21
|
+
"dateTime",
|
|
22
|
+
] as const;
|
|
23
|
+
export const timestampFormatZ = z.enum(TIMESTAMP_FORMATS);
|
|
24
|
+
export type TimestampFormat = z.infer<typeof timestampFormatZ>;
|
|
25
|
+
|
|
26
|
+
export const TIME_ZONES = ["local", "UTC"] as const;
|
|
27
|
+
export const timeZoneZ = z.enum(TIME_ZONES);
|
|
28
|
+
export type TimeZone = z.infer<typeof timeZoneZ>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * from "@/text/types";
|
|
11
|
+
export * from "@/text/types.gen";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * as text from "@/text/external";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright 2026 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
// Code generated by Oracle. DO NOT EDIT.
|
|
11
|
+
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
export const LEVELS = ["h1", "h2", "h3", "h4", "h5", "p", "small"] as const;
|
|
15
|
+
export const levelZ = z.enum(LEVELS);
|
|
16
|
+
export type Level = z.infer<typeof levelZ>;
|