@synnaxlabs/x 0.41.0 → 0.42.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.
Files changed (159) hide show
  1. package/.turbo/turbo-build.log +23 -23
  2. package/dist/binary.cjs +1 -1
  3. package/dist/binary.js +2 -2
  4. package/dist/{bounds-M-SZ3X1Z.cjs → bounds-BQo7rvs9.cjs} +1 -1
  5. package/dist/{bounds-DQrjn60Q.js → bounds-Bn5_l4Z3.js} +10 -9
  6. package/dist/bounds.cjs +1 -1
  7. package/dist/bounds.js +1 -1
  8. package/dist/compare.cjs +1 -1
  9. package/dist/compare.js +1 -1
  10. package/dist/deep.cjs +1 -1
  11. package/dist/deep.js +84 -77
  12. package/dist/{dimensions-PWy5QZoM.cjs → dimensions-D2QGoNXO.cjs} +1 -1
  13. package/dist/dimensions.cjs +1 -1
  14. package/dist/{external-CvWr1nhS.cjs → external-DWQITF5_.cjs} +1 -1
  15. package/dist/index-BywOGO8U.js +1074 -0
  16. package/dist/index-CYYjI7Uf.cjs +1 -0
  17. package/dist/index-C_6NXBlg.cjs +3 -0
  18. package/dist/{index-BVC_8Cg9.js → index-QGplUHuy.js} +1 -1
  19. package/dist/index.cjs +3 -3
  20. package/dist/index.js +702 -243
  21. package/dist/record.js +3 -1
  22. package/dist/{scale-DL9VFGhL.cjs → scale-BtZINJ-A.cjs} +1 -1
  23. package/dist/{scale-DQwBWnwc.js → scale-DfJe9755.js} +1 -1
  24. package/dist/scale.cjs +1 -1
  25. package/dist/scale.js +1 -1
  26. package/dist/{series-D0zxMWxP.js → series-B9JERcqi.js} +571 -492
  27. package/dist/series-DqJ6f97G.cjs +11 -0
  28. package/dist/spatial.cjs +1 -1
  29. package/dist/spatial.js +2 -2
  30. package/dist/src/binary/{encoder.d.ts → codec.d.ts} +14 -8
  31. package/dist/src/binary/codec.d.ts.map +1 -0
  32. package/dist/src/binary/codec.spec.d.ts +2 -0
  33. package/dist/src/binary/codec.spec.d.ts.map +1 -0
  34. package/dist/src/binary/index.d.ts +1 -1
  35. package/dist/src/binary/index.d.ts.map +1 -1
  36. package/dist/src/breaker/breaker.d.ts +14 -21
  37. package/dist/src/breaker/breaker.d.ts.map +1 -1
  38. package/dist/src/change/change.d.ts +5 -18
  39. package/dist/src/change/change.d.ts.map +1 -1
  40. package/dist/src/color/color.d.ts +126 -0
  41. package/dist/src/color/color.d.ts.map +1 -0
  42. package/dist/src/color/color.spec.d.ts +2 -0
  43. package/dist/src/color/color.spec.d.ts.map +1 -0
  44. package/dist/src/color/external.d.ts +5 -0
  45. package/dist/src/color/external.d.ts.map +1 -0
  46. package/dist/src/color/gradient.d.ts +18 -0
  47. package/dist/src/color/gradient.d.ts.map +1 -0
  48. package/dist/src/color/index.d.ts +2 -0
  49. package/dist/src/color/index.d.ts.map +1 -0
  50. package/dist/src/color/palette.d.ts +19 -0
  51. package/dist/src/color/palette.d.ts.map +1 -0
  52. package/dist/src/color/transformColorsToHex.d.ts +6 -0
  53. package/dist/src/color/transformColorsToHex.d.ts.map +1 -0
  54. package/dist/src/control/control.d.ts +69 -74
  55. package/dist/src/control/control.d.ts.map +1 -1
  56. package/dist/src/deep/merge.d.ts +1 -1
  57. package/dist/src/deep/merge.d.ts.map +1 -1
  58. package/dist/src/errors/errors.d.ts +127 -7
  59. package/dist/src/errors/errors.d.ts.map +1 -1
  60. package/dist/src/errors/errors.spec.d.ts +2 -0
  61. package/dist/src/errors/errors.spec.d.ts.map +1 -0
  62. package/dist/src/index.d.ts +4 -0
  63. package/dist/src/index.d.ts.map +1 -1
  64. package/dist/src/jsonrpc/jsonrpc.d.ts +10 -7
  65. package/dist/src/jsonrpc/jsonrpc.d.ts.map +1 -1
  66. package/dist/src/kv/types.d.ts +1 -7
  67. package/dist/src/kv/types.d.ts.map +1 -1
  68. package/dist/src/migrate/migrate.d.ts +1 -1
  69. package/dist/src/notation/notation.d.ts +5 -1
  70. package/dist/src/notation/notation.d.ts.map +1 -1
  71. package/dist/src/record.d.ts +2 -1
  72. package/dist/src/record.d.ts.map +1 -1
  73. package/dist/src/replace.d.ts +2 -0
  74. package/dist/src/replace.d.ts.map +1 -0
  75. package/dist/src/runtime/os.d.ts +9 -1
  76. package/dist/src/runtime/os.d.ts.map +1 -1
  77. package/dist/src/singleton/define.d.ts +9 -0
  78. package/dist/src/singleton/define.d.ts.map +1 -0
  79. package/dist/src/singleton/define.spec.d.ts +2 -0
  80. package/dist/src/singleton/define.spec.d.ts.map +1 -0
  81. package/dist/src/singleton/index.d.ts +2 -0
  82. package/dist/src/singleton/index.d.ts.map +1 -0
  83. package/dist/src/spatial/base.d.ts +74 -70
  84. package/dist/src/spatial/base.d.ts.map +1 -1
  85. package/dist/src/spatial/box/box.d.ts +18 -76
  86. package/dist/src/spatial/box/box.d.ts.map +1 -1
  87. package/dist/src/spatial/dimensions/dimensions.d.ts +5 -29
  88. package/dist/src/spatial/dimensions/dimensions.d.ts.map +1 -1
  89. package/dist/src/spatial/direction/direction.d.ts +9 -1
  90. package/dist/src/spatial/direction/direction.d.ts.map +1 -1
  91. package/dist/src/spatial/location/location.d.ts +43 -22
  92. package/dist/src/spatial/location/location.d.ts.map +1 -1
  93. package/dist/src/spatial/scale/scale.d.ts +12 -120
  94. package/dist/src/spatial/scale/scale.d.ts.map +1 -1
  95. package/dist/src/spatial/xy/xy.d.ts +5 -29
  96. package/dist/src/spatial/xy/xy.d.ts.map +1 -1
  97. package/dist/src/sync/index.d.ts +2 -0
  98. package/dist/src/sync/index.d.ts.map +1 -0
  99. package/dist/src/sync/mutex.d.ts +8 -0
  100. package/dist/src/sync/mutex.d.ts.map +1 -0
  101. package/dist/src/telem/gl.d.ts +4 -1
  102. package/dist/src/telem/gl.d.ts.map +1 -1
  103. package/dist/src/telem/series.d.ts +46 -125
  104. package/dist/src/telem/series.d.ts.map +1 -1
  105. package/dist/src/telem/telem.d.ts +101 -86
  106. package/dist/src/telem/telem.d.ts.map +1 -1
  107. package/dist/src/toArray.d.ts +1 -1
  108. package/dist/src/toArray.d.ts.map +1 -1
  109. package/dist/src/zod/util.d.ts.map +1 -1
  110. package/dist/telem.cjs +1 -1
  111. package/dist/telem.js +1 -1
  112. package/dist/toArray.cjs +1 -1
  113. package/dist/toArray.js +1 -1
  114. package/dist/zod.cjs +1 -1
  115. package/package.json +5 -2
  116. package/src/binary/codec.spec.ts +370 -0
  117. package/src/binary/{encoder.ts → codec.ts} +55 -11
  118. package/src/binary/index.ts +1 -1
  119. package/src/breaker/breaker.spec.ts +16 -25
  120. package/src/breaker/breaker.ts +36 -19
  121. package/src/color/color.spec.ts +673 -0
  122. package/src/color/color.ts +317 -0
  123. package/src/color/external.ts +13 -0
  124. package/src/color/gradient.ts +78 -0
  125. package/src/color/index.ts +10 -0
  126. package/src/color/palette.ts +28 -0
  127. package/src/color/transformColorsToHex.ts +30 -0
  128. package/src/control/control.ts +30 -22
  129. package/src/deep/merge.spec.ts +60 -0
  130. package/src/deep/merge.ts +13 -8
  131. package/src/errors/errors.spec.ts +152 -0
  132. package/src/errors/errors.ts +225 -10
  133. package/src/index.ts +4 -0
  134. package/src/jsonrpc/jsonrpc.ts +12 -8
  135. package/src/migrate/migrate.ts +2 -2
  136. package/src/primitive.ts +1 -1
  137. package/src/record.ts +5 -1
  138. package/src/replace.ts +1 -0
  139. package/src/singleton/define.spec.ts +93 -0
  140. package/src/singleton/define.ts +27 -0
  141. package/src/singleton/index.ts +10 -0
  142. package/src/sync/index.ts +1 -0
  143. package/src/sync/mutex.ts +16 -0
  144. package/src/telem/series.spec.ts +32 -0
  145. package/src/telem/series.ts +54 -19
  146. package/src/telem/telem.spec.ts +151 -10
  147. package/src/telem/telem.ts +126 -73
  148. package/src/toArray.ts +2 -2
  149. package/src/zod/util.spec.ts +17 -1
  150. package/src/zod/util.ts +4 -2
  151. package/tsconfig.tsbuildinfo +1 -1
  152. package/dist/index-BG3Scw3G.cjs +0 -1
  153. package/dist/index-C3QzbIwt.js +0 -101
  154. package/dist/index-CnclyYpG.cjs +0 -3
  155. package/dist/series-BMma2b5q.cjs +0 -11
  156. package/dist/src/binary/encoder.d.ts.map +0 -1
  157. package/dist/src/binary/encoder.spec.d.ts +0 -2
  158. package/dist/src/binary/encoder.spec.d.ts.map +0 -1
  159. package/src/binary/encoder.spec.ts +0 -174
@@ -107,6 +107,13 @@ describe("Series", () => {
107
107
  expect(s.length).toEqual(3);
108
108
  });
109
109
 
110
+ it("should construct a series from an int32 array", () => {
111
+ const s = new Series(new Int32Array([1, 2, 3]));
112
+ expect(s.dataType.equals(DataType.INT32)).toBeTruthy();
113
+ expect(s.length).toEqual(3);
114
+ expect(Array.from(s)).toEqual([1, 2, 3]);
115
+ });
116
+
110
117
  it("should assume string when a single string is passed as data", () => {
111
118
  const s = new Series("abc");
112
119
  expect(s.dataType.equals(DataType.STRING)).toBeTruthy();
@@ -762,6 +769,31 @@ describe("Series", () => {
762
769
  });
763
770
  });
764
771
 
772
+ describe("toString", () => {
773
+ interface Spec {
774
+ series: Series;
775
+ expected: string;
776
+ }
777
+ const SPECS: Spec[] = [
778
+ {
779
+ series: new Series({ data: [1, 2, 3, 4], dataType: "float64" }),
780
+ expected: "float64 4 [1,2,3,4]",
781
+ },
782
+ {
783
+ series: new Series({
784
+ data: Array.from({ length: 100 }, (_, i) => i),
785
+ dataType: "float32",
786
+ }),
787
+ expected: "float32 100 [0,1,2,3,4...95,96,97,98,99]",
788
+ },
789
+ ];
790
+ SPECS.forEach(({ series, expected }) => {
791
+ it(`should convert ${series.toString()} to a string`, () => {
792
+ expect(series.toString()).toEqual(expected);
793
+ });
794
+ });
795
+ });
796
+
765
797
  describe("sub", () => {
766
798
  it("should return a sub-series backed by the same buffer", () => {
767
799
  const arr = new Float32Array([1, 2, 3, 4, 5]);
@@ -158,7 +158,7 @@ export class Series<T extends TelemValue = TelemValue> {
158
158
  private readonly gl: GL;
159
159
  /** The underlying data. */
160
160
  private readonly _data: ArrayBuffer;
161
- readonly _timeRange?: TimeRange;
161
+ readonly timeRange: TimeRange = TimeRange.ZERO;
162
162
  readonly alignment: bigint = 0n;
163
163
  /** A cached minimum value. */
164
164
  private _cachedMin?: math.Numeric;
@@ -211,7 +211,7 @@ export class Series<T extends TelemValue = TelemValue> {
211
211
  this.sampleOffset = data_.sampleOffset;
212
212
  this.gl = data_.gl;
213
213
  this._data = data_._data;
214
- this._timeRange = data_._timeRange;
214
+ this.timeRange = data_.timeRange;
215
215
  this.alignment = data_.alignment;
216
216
  this._cachedMin = data_._cachedMin;
217
217
  this._cachedMax = data_._cachedMax;
@@ -287,7 +287,7 @@ export class Series<T extends TelemValue = TelemValue> {
287
287
  this.key = key;
288
288
  this.alignment = alignment;
289
289
  this.sampleOffset = sampleOffset ?? 0;
290
- this._timeRange = timeRange;
290
+ this.timeRange = timeRange ?? TimeRange.ZERO;
291
291
  this.gl = {
292
292
  control: null,
293
293
  buffer: null,
@@ -341,11 +341,13 @@ export class Series<T extends TelemValue = TelemValue> {
341
341
  }
342
342
 
343
343
  release(): void {
344
+ if (this._refCount <= 0) {
345
+ console.warn("attempted to release a series with a negative reference count");
346
+ return;
347
+ }
344
348
  this._refCount--;
345
349
  if (this._refCount === 0 && this.gl.control != null)
346
350
  this.maybeGarbageCollectGLBuffer(this.gl.control);
347
- else if (this._refCount < 0)
348
- throw new Error("cannot release an array with a negative reference count");
349
351
  }
350
352
 
351
353
  /**
@@ -445,12 +447,6 @@ export class Series<T extends TelemValue = TelemValue> {
445
447
  .map((s) => schema.parse(binary.JSON_CODEC.decodeString(s)));
446
448
  }
447
449
 
448
- /** @returns the time range of this array. */
449
- get timeRange(): TimeRange {
450
- if (this._timeRange == null) throw new Error("time range not set on series");
451
- return this._timeRange;
452
- }
453
-
454
450
  /** @returns the capacity of the series in bytes. */
455
451
  get byteCapacity(): Size {
456
452
  return new Size(this.underlyingData.byteLength);
@@ -509,7 +505,7 @@ export class Series<T extends TelemValue = TelemValue> {
509
505
  return new Series({
510
506
  data: data.buffer,
511
507
  dataType: target,
512
- timeRange: this._timeRange,
508
+ timeRange: this.timeRange,
513
509
  sampleOffset,
514
510
  glBufferUsage: this.gl.bufferUsage,
515
511
  alignment: this.alignment,
@@ -720,7 +716,7 @@ export class Series<T extends TelemValue = TelemValue> {
720
716
  lower: alignmentDigest(this.alignmentBounds.lower),
721
717
  upper: alignmentDigest(this.alignmentBounds.upper),
722
718
  },
723
- timeRange: this._timeRange?.toString(),
719
+ timeRange: this.timeRange?.toString(),
724
720
  length: this.length,
725
721
  capacity: this.capacity,
726
722
  };
@@ -789,7 +785,7 @@ export class Series<T extends TelemValue = TelemValue> {
789
785
  return new Series({
790
786
  data,
791
787
  dataType: this.dataType,
792
- timeRange: this._timeRange,
788
+ timeRange: this.timeRange,
793
789
  sampleOffset: this.sampleOffset,
794
790
  glBufferUsage: this.gl.bufferUsage,
795
791
  alignment: this.alignment + BigInt(start),
@@ -804,7 +800,7 @@ export class Series<T extends TelemValue = TelemValue> {
804
800
  return new Series({
805
801
  data,
806
802
  dataType: this.dataType,
807
- timeRange: this._timeRange,
803
+ timeRange: this.timeRange,
808
804
  sampleOffset: this.sampleOffset,
809
805
  glBufferUsage: this.gl.bufferUsage,
810
806
  alignment: this.alignment + BigInt(start),
@@ -821,6 +817,24 @@ export class Series<T extends TelemValue = TelemValue> {
821
817
  alignment,
822
818
  });
823
819
  }
820
+
821
+ toString(): string {
822
+ let data = `${this.dataType.toString()} ${this.length} [`;
823
+ if (this.length <= 10) data += Array.from(this).map((v) => v.toString());
824
+ else {
825
+ for (let i = 0; i < 5; i++) {
826
+ data += `${this.at(i)?.toString()}`;
827
+ if (i < 4) data += ",";
828
+ }
829
+ data += "...";
830
+ for (let i = -5; i < 0; i++) {
831
+ data += this.at(i)?.toString();
832
+ if (i < -1) data += ",";
833
+ }
834
+ }
835
+ data += "]";
836
+ return data;
837
+ }
824
838
  }
825
839
 
826
840
  class SubIterator<T> implements Iterator<T>, Iterable<T> {
@@ -878,6 +892,7 @@ class StringSeriesIterator implements Iterator<string> {
878
892
 
879
893
  class JSONSeriesIterator implements Iterator<unknown> {
880
894
  private readonly wrapped: Iterator<string>;
895
+ private static SCHEMA = z.record(z.string(), z.unknown());
881
896
 
882
897
  constructor(wrapped: Iterator<string>) {
883
898
  this.wrapped = wrapped;
@@ -888,7 +903,7 @@ class JSONSeriesIterator implements Iterator<unknown> {
888
903
  if (next.done === true) return { done: true, value: undefined };
889
904
  return {
890
905
  done: false,
891
- value: binary.JSON_CODEC.decodeString(next.value),
906
+ value: binary.JSON_CODEC.decodeString(next.value, JSONSeriesIterator.SCHEMA),
892
907
  };
893
908
  }
894
909
 
@@ -925,7 +940,7 @@ class FixedSeriesIterator implements Iterator<math.Numeric> {
925
940
  export class MultiSeries<T extends TelemValue = TelemValue> implements Iterable<T> {
926
941
  readonly series: Array<Series<T>>;
927
942
 
928
- constructor(series: Array<Series<T>>) {
943
+ constructor(series: Array<Series<T>> = []) {
929
944
  if (series.length !== 0) {
930
945
  const type = series[0].dataType;
931
946
  for (let i = 1; i < series.length; i++)
@@ -972,8 +987,12 @@ export class MultiSeries<T extends TelemValue = TelemValue> implements Iterable<
972
987
  );
973
988
  }
974
989
 
975
- push(series: Series<T>): void {
976
- this.series.push(series);
990
+ push(series: Series<T>): void;
991
+ push(series: MultiSeries<T>): void;
992
+
993
+ push(series: Series<T> | MultiSeries<T>): void {
994
+ if ("isSynnaxSeries" in series && series.isSynnaxSeries) this.series.push(series);
995
+ else this.series.push(...(series as MultiSeries<T>).series);
977
996
  }
978
997
 
979
998
  get length(): number {
@@ -1055,6 +1074,14 @@ export class MultiSeries<T extends TelemValue = TelemValue> implements Iterable<
1055
1074
  return new MultiSubIterator(this, startIdx, startIdx + span);
1056
1075
  }
1057
1076
 
1077
+ updateGLBuffer(gl: GLBufferController): void {
1078
+ this.series.forEach((s) => s.updateGLBuffer(gl));
1079
+ }
1080
+
1081
+ get bounds(): bounds.Bounds {
1082
+ return bounds.max(this.series.map((s) => s.bounds));
1083
+ }
1084
+
1058
1085
  get byteLength(): Size {
1059
1086
  return new Size(this.series.reduce((a, b) => a + b.byteLength.valueOf(), 0));
1060
1087
  }
@@ -1074,6 +1101,14 @@ export class MultiSeries<T extends TelemValue = TelemValue> implements Iterable<
1074
1101
  return bounds.traverse(b, start, dist);
1075
1102
  }
1076
1103
 
1104
+ acquire(): void {
1105
+ this.series.forEach((s) => s.acquire());
1106
+ }
1107
+
1108
+ release(): void {
1109
+ this.series.forEach((s) => s.release());
1110
+ }
1111
+
1077
1112
  distance(start: bigint, end: bigint): bigint {
1078
1113
  const b = this.series.map((s) => s.alignmentBounds);
1079
1114
  return bounds.distance(b, start, end);
@@ -19,6 +19,7 @@ import {
19
19
  TimeRange,
20
20
  TimeSpan,
21
21
  TimeStamp,
22
+ type TimeStampStringFormat,
22
23
  } from "@/telem";
23
24
 
24
25
  describe("TimeStamp", () => {
@@ -177,19 +178,159 @@ describe("TimeStamp", () => {
177
178
  expect(ts.sub(TimeSpan.microseconds()).equals(new TimeStamp(0))).toBeTruthy();
178
179
  });
179
180
 
180
- test("stringification", () => {
181
+ describe("fString", () => {
181
182
  const ts = new TimeStamp([2022, 12, 15], "UTC")
182
183
  .add(TimeSpan.hours(12))
183
184
  .add(TimeSpan.minutes(20))
184
185
  .add(TimeSpan.milliseconds(12));
185
- expect(ts.fString("ISO", "UTC")).toEqual("2022-12-15T12:20:00.012Z");
186
- expect(ts.fString("time", "UTC")).toEqual("12:20:00");
187
- expect(ts.fString("date", "UTC")).toEqual("Dec 15");
188
- if (!TimeStamp.utcOffset.equals(0)) {
189
- expect(ts.fString("ISO", "local")).not.toEqual("2022-12-15T12:20:00.012Z");
190
- expect(ts.fString("time", "local")).not.toEqual("12:20:00");
191
- }
186
+
187
+ const FORMAT_TESTS: [TimeStampStringFormat, string][] = [
188
+ ["ISO", "2022-12-15T12:20:00.012Z"],
189
+ ["ISODate", "2022-12-15"],
190
+ ["ISOTime", "12:20:00.012"],
191
+ ["time", "12:20:00"],
192
+ ["preciseTime", "12:20:00.012"],
193
+ ["date", "Dec 15"],
194
+ ["preciseDate", "Dec 15 12:20:00.012"],
195
+ ["dateTime", "Dec 15 12:20:00"],
196
+ ];
197
+
198
+ FORMAT_TESTS.forEach(([format, expected]) => {
199
+ test(`should format timestamp as ${format}`, () => {
200
+ expect(ts.fString(format, "UTC")).toEqual(expected);
201
+ });
202
+ });
192
203
  });
204
+
205
+ describe("unit getters", () => {
206
+ test("hour", () => {
207
+ expect(TimeStamp.hours(1).add(TimeSpan.minutes(30)).hour).toEqual(1);
208
+ });
209
+ test("hours", () => {
210
+ expect(TimeStamp.hours(1).add(TimeSpan.minutes(30)).hours).toEqual(1.5);
211
+ });
212
+ test("minute", () => {
213
+ expect(TimeStamp.minutes(1).add(TimeStamp.seconds(20)).minute).toEqual(1);
214
+ });
215
+ test("minutes", () => {
216
+ expect(TimeStamp.minutes(1).add(TimeStamp.seconds(30)).minutes).toEqual(1.5);
217
+ });
218
+ test("second", () => {
219
+ expect(TimeStamp.seconds(1).add(TimeStamp.milliseconds(20)).second).toEqual(1);
220
+ });
221
+ test("seconds", () => {
222
+ expect(TimeStamp.seconds(1).add(TimeStamp.milliseconds(500)).seconds).toEqual(
223
+ 1.5,
224
+ );
225
+ });
226
+ test("millisecond", () => {
227
+ expect(
228
+ TimeStamp.milliseconds(1).add(TimeStamp.microseconds(20)).millisecond,
229
+ ).toEqual(1);
230
+ });
231
+ test("milliseconds", () => {
232
+ expect(
233
+ TimeStamp.milliseconds(1).add(TimeStamp.microseconds(500)).milliseconds,
234
+ ).toEqual(1.5);
235
+ });
236
+ test("microseconds", () => {
237
+ expect(
238
+ TimeStamp.microseconds(500).add(TimeSpan.nanoseconds(20)).microseconds,
239
+ ).toEqual(500.02);
240
+ });
241
+ test("nanoseconds", () => {
242
+ expect(
243
+ TimeStamp.microseconds(1).add(TimeSpan.nanoseconds(30)).nanoseconds,
244
+ ).toEqual(1030);
245
+ });
246
+ test("year", () => {
247
+ expect(new TimeStamp([2022, 12, 15]).year).toEqual(2022);
248
+ });
249
+ test("month", () => {
250
+ expect(new TimeStamp([2022, 12, 15]).month).toEqual(11);
251
+ });
252
+ test("day", () => {
253
+ expect(new TimeStamp([2022, 12, 15]).day).toEqual(15);
254
+ });
255
+ });
256
+
257
+ describe("unit setters", () => {
258
+ test("setYear", () => {
259
+ const ts = new TimeStamp([2022, 12, 15]);
260
+ const updated = ts.setYear(2023);
261
+ expect(updated.year).toEqual(2023);
262
+ expect(updated.month).toEqual(ts.month); // Other components should remain unchanged
263
+ expect(updated.day).toEqual(ts.day);
264
+ });
265
+
266
+ test("setMonth", () => {
267
+ const ts = new TimeStamp([2022, 12, 15]);
268
+ const updated = ts.setMonth(5); // June (0-indexed)
269
+ expect(updated.month).toEqual(5);
270
+ expect(updated.year).toEqual(ts.year); // Other components should remain unchanged
271
+ expect(updated.day).toEqual(ts.day);
272
+ });
273
+
274
+ test("setDay", () => {
275
+ const ts = new TimeStamp([2022, 12, 15]);
276
+ const updated = ts.setDay(20);
277
+ expect(updated.day).toEqual(20);
278
+ expect(updated.year).toEqual(ts.year);
279
+ expect(updated.month).toEqual(ts.month);
280
+ });
281
+
282
+ test("setHour", () => {
283
+ const ts = new TimeStamp([2022, 12, 15]).add(TimeSpan.hours(10));
284
+ const updated = ts.setHour(15);
285
+ expect(updated.hour).toEqual(15);
286
+ expect(updated.year).toEqual(ts.year);
287
+ expect(updated.month).toEqual(ts.month);
288
+ expect(updated.day).toEqual(ts.day);
289
+ });
290
+
291
+ test("setMinute", () => {
292
+ const ts = new TimeStamp([2022, 12, 15])
293
+ .add(TimeSpan.hours(10))
294
+ .add(TimeSpan.minutes(30));
295
+ const updated = ts.setMinute(45);
296
+ expect(updated.minute).toEqual(45);
297
+ expect(updated.hour).toEqual(ts.hour);
298
+ expect(updated.year).toEqual(ts.year);
299
+ expect(updated.month).toEqual(ts.month);
300
+ expect(updated.day).toEqual(ts.day);
301
+ });
302
+
303
+ test("setSecond", () => {
304
+ const ts = new TimeStamp([2022, 12, 15])
305
+ .add(TimeSpan.hours(10))
306
+ .add(TimeSpan.minutes(30))
307
+ .add(TimeSpan.seconds(20));
308
+ const updated = ts.setSecond(45);
309
+ expect(updated.second).toEqual(45);
310
+ expect(updated.minute).toEqual(ts.minute); // Other components should remain unchanged
311
+ expect(updated.hour).toEqual(ts.hour);
312
+ expect(updated.year).toEqual(ts.year);
313
+ expect(updated.month).toEqual(ts.month);
314
+ expect(updated.day).toEqual(ts.day);
315
+ });
316
+
317
+ test("setMillisecond", () => {
318
+ const ts = new TimeStamp([2022, 12, 15])
319
+ .add(TimeSpan.hours(10))
320
+ .add(TimeSpan.minutes(30))
321
+ .add(TimeSpan.seconds(20))
322
+ .add(TimeSpan.milliseconds(100));
323
+ const updated = ts.setMillisecond(500);
324
+ expect(updated.millisecond).toEqual(500);
325
+ expect(updated.second).toEqual(ts.second); // Other components should remain unchanged
326
+ expect(updated.minute).toEqual(ts.minute);
327
+ expect(updated.hour).toEqual(ts.hour);
328
+ expect(updated.year).toEqual(ts.year);
329
+ expect(updated.month).toEqual(ts.month);
330
+ expect(updated.day).toEqual(ts.day);
331
+ });
332
+ });
333
+
193
334
  describe("remainder", () => {
194
335
  test("day", () => {
195
336
  const expectedRemainder = TimeStamp.hours(12)
@@ -463,8 +604,8 @@ describe("TimeRange", () => {
463
604
  TimeSpan.seconds(1),
464
605
  TimeSpan.seconds(4).add(TimeSpan.milliseconds(500)),
465
606
  );
466
- expect(tr.roughlyEquals(one, TimeSpan.seconds(1))).toBeTruthy();
467
- expect(tr.roughlyEquals(one, TimeSpan.seconds(0))).toBeFalsy();
607
+ expect(tr.equals(one, TimeSpan.seconds(1))).toBeTruthy();
608
+ expect(tr.equals(one, TimeSpan.seconds(0))).toBeFalsy();
468
609
  });
469
610
  });
470
611