aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-util/src/time.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-05-26 13:52:00 +0200
committerFlorian Dold <florian@dold.me>2023-05-26 13:52:00 +0200
commit96d9ea3840626f71efe38018b75748d8338565fa (patch)
treed1f04ecbb58750af79b3d0cb0420ba4fdf6d05a2 /packages/taler-util/src/time.ts
parentcd8f76db61f4a1ab1a8a8a4d29b2f3e863b59854 (diff)
downloadwallet-core-96d9ea3840626f71efe38018b75748d8338565fa.tar.gz
wallet-core-96d9ea3840626f71efe38018b75748d8338565fa.tar.bz2
wallet-core-96d9ea3840626f71efe38018b75748d8338565fa.zip
taler-util,wallet-core: make AbsoluteTime opaque
Diffstat (limited to 'packages/taler-util/src/time.ts')
-rw-r--r--packages/taler-util/src/time.ts66
1 files changed, 47 insertions, 19 deletions
diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts
index 697bde5c0..717da7ecd 100644
--- a/packages/taler-util/src/time.ts
+++ b/packages/taler-util/src/time.ts
@@ -27,6 +27,8 @@ declare const flavor_AbsoluteTime: unique symbol;
declare const flavor_TalerProtocolTimestamp: unique symbol;
declare const flavor_TalerPreciseTimestamp: unique symbol;
+const opaque_AbsoluteTime: unique symbol = Symbol("opaque_AbsoluteTime");
+
// FIXME: Make this opaque!
export interface AbsoluteTime {
/**
@@ -35,6 +37,10 @@ export interface AbsoluteTime {
readonly t_ms: number | "never";
readonly _flavor?: typeof flavor_AbsoluteTime;
+
+ // Make the type opaque, we only want our constructors
+ // to able to create an AbsoluteTime value.
+ [opaque_AbsoluteTime]: true;
}
export interface TalerProtocolTimestamp {
@@ -69,7 +75,7 @@ export namespace TalerPreciseTimestamp {
export function round(t: TalerPreciseTimestamp): TalerProtocolTimestamp {
return {
t_s: t.t_s,
- }
+ };
}
export function fromSeconds(s: number): TalerPreciseTimestamp {
@@ -78,6 +84,13 @@ export namespace TalerPreciseTimestamp {
off_us: (s - Math.floor(s)) / 1000 / 1000,
};
}
+
+ export function fromMilliseconds(ms: number): TalerPreciseTimestamp {
+ return {
+ t_s: Math.floor(ms / 1000),
+ off_us: Math.floor((ms - Math.floor(ms / 100) * 1000) * 1000),
+ }
+ }
}
export namespace TalerProtocolTimestamp {
@@ -269,12 +282,21 @@ export namespace AbsoluteTime {
export function now(): AbsoluteTime {
return {
t_ms: new Date().getTime() + timeshift,
+ [opaque_AbsoluteTime]: true,
};
}
export function never(): AbsoluteTime {
return {
t_ms: "never",
+ [opaque_AbsoluteTime]: true,
+ };
+ }
+
+ export function fromMilliseconds(ms: number): AbsoluteTime {
+ return {
+ t_ms: ms,
+ [opaque_AbsoluteTime]: true,
};
}
@@ -299,22 +321,22 @@ export namespace AbsoluteTime {
export function min(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {
if (t1.t_ms === "never") {
- return { t_ms: t2.t_ms };
+ return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true };
}
if (t2.t_ms === "never") {
- return { t_ms: t2.t_ms };
+ return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true };
}
- return { t_ms: Math.min(t1.t_ms, t2.t_ms) };
+ return { t_ms: Math.min(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true };
}
export function max(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime {
if (t1.t_ms === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
if (t2.t_ms === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
- return { t_ms: Math.max(t1.t_ms, t2.t_ms) };
+ return { t_ms: Math.max(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true };
}
export function difference(t1: AbsoluteTime, t2: AbsoluteTime): Duration {
@@ -331,22 +353,26 @@ export namespace AbsoluteTime {
return cmp(t, now()) <= 0;
}
- export function fromProtocolTimestamp(t: TalerProtocolTimestamp): AbsoluteTime {
+ export function fromProtocolTimestamp(
+ t: TalerProtocolTimestamp,
+ ): AbsoluteTime {
if (t.t_s === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
return {
t_ms: t.t_s * 1000,
+ [opaque_AbsoluteTime]: true,
};
}
export function fromPreciseTimestamp(t: TalerPreciseTimestamp): AbsoluteTime {
if (t.t_s === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
const offsetUs = t.off_us ?? 0;
return {
t_ms: t.t_s * 1000 + offsetUs / 1000,
+ [opaque_AbsoluteTime]: true,
};
}
@@ -361,10 +387,12 @@ export namespace AbsoluteTime {
return {
t_s,
off_us,
- }
+ };
}
- export function toProtocolTimestamp(at: AbsoluteTime): TalerProtocolTimestamp {
+ export function toProtocolTimestamp(
+ at: AbsoluteTime,
+ ): TalerProtocolTimestamp {
if (at.t_ms === "never") {
return { t_s: "never" };
}
@@ -397,9 +425,9 @@ export namespace AbsoluteTime {
export function addDuration(t1: AbsoluteTime, d: Duration): AbsoluteTime {
if (t1.t_ms === "never" || d.d_ms === "forever") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
- return { t_ms: t1.t_ms + d.d_ms };
+ return { t_ms: t1.t_ms + d.d_ms, [opaque_AbsoluteTime]: true };
}
export function subtractDuraction(
@@ -407,12 +435,12 @@ export namespace AbsoluteTime {
d: Duration,
): AbsoluteTime {
if (t1.t_ms === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
if (d.d_ms === "forever") {
- return { t_ms: 0 };
+ return { t_ms: 0, [opaque_AbsoluteTime]: true };
}
- return { t_ms: Math.max(0, t1.t_ms - d.d_ms) };
+ return { t_ms: Math.max(0, t1.t_ms - d.d_ms), [opaque_AbsoluteTime]: true };
}
export function stringify(t: AbsoluteTime): string {
@@ -487,10 +515,10 @@ export const codecForAbsoluteTime: Codec<AbsoluteTime> = {
const t_ms = x.t_ms;
if (typeof t_ms === "string") {
if (t_ms === "never") {
- return { t_ms: "never" };
+ return { t_ms: "never", [opaque_AbsoluteTime]: true };
}
} else if (typeof t_ms === "number") {
- return { t_ms };
+ return { t_ms, [opaque_AbsoluteTime]: true };
}
throw Error(`expected timestamp at ${renderContext(c)}`);
},