78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
import type {
|
|
BitPackerSchema,
|
|
PackingContext,
|
|
PackingStrategy,
|
|
} from "@suaveplan/bitpacker";
|
|
import { BITPACKER_CODES, BitpackerError } from "@suaveplan/bitpacker";
|
|
|
|
const DATETIME_TOKENS: readonly string[] = [
|
|
"timestamp",
|
|
"timestamp-ms",
|
|
"timestamp-s",
|
|
"timespan",
|
|
"timespan-ms",
|
|
"date-only",
|
|
];
|
|
|
|
export class DateTimePackingStrategy implements PackingStrategy {
|
|
canHandle(schema: BitPackerSchema): boolean {
|
|
return typeof schema === "string" && DATETIME_TOKENS.includes(schema);
|
|
}
|
|
|
|
pack(
|
|
data: unknown,
|
|
schema: BitPackerSchema,
|
|
context: PackingContext
|
|
): void {
|
|
const token = schema as string;
|
|
let ms: number;
|
|
|
|
if (data instanceof Date) {
|
|
ms = data.getTime();
|
|
} else if (typeof data === "number") {
|
|
ms = data;
|
|
} else {
|
|
throw new BitpackerError(
|
|
BITPACKER_CODES.INVALID_SCHEMA,
|
|
`Expected Date or number for datetime schema "${token}", got ${typeof data}`,
|
|
{ context: { token, data } }
|
|
);
|
|
}
|
|
|
|
switch (token) {
|
|
case "timestamp":
|
|
case "timestamp-ms":
|
|
case "date-only":
|
|
context.writer.writeInt(ms, 53);
|
|
break;
|
|
case "timestamp-s":
|
|
context.writer.writeInt(Math.floor(ms / 1000), 32);
|
|
break;
|
|
case "timespan":
|
|
context.writer.writeInt(ms, 53);
|
|
break;
|
|
case "timespan-ms":
|
|
context.writer.writeInt(ms, 53);
|
|
break;
|
|
}
|
|
}
|
|
|
|
unpack(schema: BitPackerSchema, context: PackingContext): unknown {
|
|
const token = schema as string;
|
|
|
|
switch (token) {
|
|
case "timestamp":
|
|
case "timestamp-ms":
|
|
case "date-only":
|
|
return context.reader.readInt(53);
|
|
case "timestamp-s":
|
|
return context.reader.readInt(32) * 1000;
|
|
case "timespan":
|
|
case "timespan-ms":
|
|
return context.reader.readInt(53);
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
}
|