UNPKG

@tai-kun/surrealdb

Version:

The SurrealDB SDK for JavaScript

87 lines (74 loc) 2.28 kB
import type { DataItem } from "@tai-kun/surrealdb/cbor"; import { defineAsDatetime } from "../_internals/define"; // See: https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml // SurrealDB では日時にタグ 100, 1, 1004 を使っていない模様 export type DatetimeSource = // Tag 0 (, 100) | DataItem.Utf8String.FixedLength["value"] // Tag (1, 1004) // | DataItem.UnsignedInteger["value"] // | DataItem.NegativeInteger["value"] // SurrealDB 独自 | readonly [ // i64 seconds: | DataItem.UnsignedInteger["value"] | DataItem.NegativeInteger["value"], // u32 nanoseconds: | DataItem.UnsignedInteger.Tiny["value"] | DataItem.UnsignedInteger.OneByte["value"] | DataItem.UnsignedInteger.TwoBytes["value"] | DataItem.UnsignedInteger.FourBytes["value"], ]; const MILLISECONDS_PER_SECOND = 1e3; const NANOSECONDS_PER_MILLISECOND = 1e6; const NANOSECONDS_PER_SECOND = 1e9; const MAX_DATE_SECONDS = 8_640_000_000_000; const MIN_DATE_SECONDS = -8_640_000_000_000; /** * [API Reference](https://tai-kun.github.io/surrealdb.js/v2/api/data/datetime) */ export default class Datetime { /** * -(2^53-1) ~ 2^53-1, NaN */ readonly seconds: number; /** * 0 ~ 999_999_999, NaN */ readonly nanoseconds: number; constructor(source: DatetimeSource) { let s: number, ns: number; if (typeof source === "string") { const msTime = Date.parse(source); if (msTime === msTime) { s = Math.trunc(msTime / MILLISECONDS_PER_SECOND); ns = Math.abs( (msTime % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND, ); if (s <= 0 && ns > 0) { if (s <= MIN_DATE_SECONDS) { s = ns = NaN; // Underflow } else { s -= 1; ns = NANOSECONDS_PER_SECOND - ns; } } } else { s = ns = NaN; } } else { ns = source[1]; s = Number(source[0]) + Math.trunc(ns / NANOSECONDS_PER_SECOND); if (s >= MIN_DATE_SECONDS && s <= MAX_DATE_SECONDS) { ns %= NANOSECONDS_PER_SECOND; } else { s = ns = NaN; } } this.seconds = s === 0 ? 0 : s; this.nanoseconds = ns === 0 ? 0 : ns; defineAsDatetime(this); } }