@datastax/astra-db-ts
Version:
Data API TypeScript client
233 lines (232 loc) • 9.61 kB
JavaScript
;
// Copyright Datastax, Inc
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.time = exports.DataAPITime = void 0;
const constants_js_1 = require("../../lib/constants.js");
const constants_js_2 = require("../../documents/collections/ser-des/constants.js");
const constants_js_3 = require("../../documents/tables/ser-des/constants.js");
const utils_js_1 = require("../../documents/utils.js");
const utils_js_2 = require("../../lib/api/ser-des/utils.js");
class DataAPITime {
[constants_js_2.$SerializeForCollection]() {
throw (0, utils_js_2.mkTypeUnsupportedForCollectionsError)('DataAPITime', '_time', [
'Use a native Javascript Date object',
'Use another time representation, such as a string, or an object containing the hours, minutes, seconds, and nanoseconds',
]);
}
;
[constants_js_3.$SerializeForTable](ctx) {
return ctx.done(this.toString());
}
;
static [constants_js_3.$DeserializeForTable](value, ctx) {
return ctx.done(new DataAPITime(value));
}
static now() {
return new DataAPITime(new Date());
}
static utcnow() {
return new DataAPITime(...ofNanoOfDay((Date.now() % 86400000) * 1000000));
}
static ofNanoOfDay(nanoOfDay) {
return new DataAPITime(...ofNanoOfDay(nanoOfDay));
}
static ofSecondOfDay(secondOfDay) {
return new DataAPITime(...ofSecondOfDay(secondOfDay));
}
constructor(i1, i2, i3, i4) {
Object.defineProperty(this, "hours", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "minutes", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "seconds", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "nanoseconds", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
switch (arguments.length) {
case 1: {
if (typeof i1 === 'string') {
[this.hours, this.minutes, this.seconds, this.nanoseconds] = parseTimeStr(i1, true);
}
else if (i1 instanceof Date) {
if (isNaN(i1.getTime())) {
throw new Error(`Invalid date '${i1.toString()}'; must be a valid (non-NaN) date`);
}
this.hours = i1.getHours();
this.minutes = i1.getMinutes();
this.seconds = i1.getSeconds();
this.nanoseconds = i1.getMilliseconds() * 1000000;
}
else {
throw (0, utils_js_1.mkInvArgsError)('new DataAPITime', [['time', 'string | Date']], i1);
}
break;
}
case 2:
case 3:
case 4: {
if (typeof i1 === 'string') {
[this.hours, this.minutes, this.seconds, this.nanoseconds] = parseTimeStr(i1, i2 !== false);
}
else if (typeof i1 === 'number' && typeof i2 === 'number' && (!i3 || typeof i3 === 'number') && (!i4 || typeof i4 === 'number')) {
this.hours = i1;
this.minutes = i2;
this.seconds = i3 || 0;
this.nanoseconds = i4 || 0;
validateTime(this.hours, this.minutes, this.seconds, this.nanoseconds);
}
else {
throw (0, utils_js_1.mkInvArgsError)('new DataAPIDate', [['hour', 'number'], ['minute', 'number'], ['second', 'number?'], ['nanosecond', 'number?']], i1, i2, i3, i4);
}
break;
}
default: {
throw RangeError(`Invalid number of arguments; expected 1..=4, got ${arguments.length}`);
}
}
Object.defineProperty(this, constants_js_1.$CustomInspect, {
value: () => `DataAPITime("${this.toString()}")`,
});
}
toDate(base) {
base || (base = new Date());
if (base instanceof Date) {
return new Date(base.getFullYear(), base.getMonth(), base.getDate(), this.hours, this.minutes, this.seconds, this.nanoseconds / 1000000);
}
return new Date(base.year, base.month - 1, base.date, this.hours, this.minutes, this.seconds, this.nanoseconds / 1000000);
}
toDateUTC(base) {
base || (base = new Date());
if (base instanceof Date) {
return new Date(Date.UTC(base.getUTCFullYear(), base.getUTCMonth(), base.getUTCDate(), this.hours, this.minutes, this.seconds, this.nanoseconds / 1000000));
}
return new Date(Date.UTC(base.year, base.month - 1, base.date, this.hours, this.minutes, this.seconds, this.nanoseconds / 1000000));
}
toString() {
return `${this.hours.toString().padStart(2, '0')}:${this.minutes.toString().padStart(2, '0')}:${this.seconds.toString().padStart(2, '0')}.${this.nanoseconds.toString().padStart(9, '0')}`;
}
compare(other) {
if (this.hours !== other.hours) {
return this.hours < other.hours ? -1 : 1;
}
if (this.minutes !== other.minutes) {
return this.minutes < other.minutes ? -1 : 1;
}
if (this.seconds !== other.seconds) {
return this.seconds < other.seconds ? -1 : 1;
}
if (this.nanoseconds !== other.nanoseconds) {
return this.nanoseconds < other.nanoseconds ? -1 : 1;
}
return 0;
}
equals(other) {
return (other instanceof DataAPITime) && this.compare(other) === 0;
}
}
exports.DataAPITime = DataAPITime;
exports.time = Object.assign((...params) => (params[0] instanceof DataAPITime) ? params[0] : new DataAPITime(...params), {
now: DataAPITime.now,
utcnow: DataAPITime.utcnow,
ofNanoOfDay: DataAPITime.ofNanoOfDay,
ofSecondOfDay: DataAPITime.ofSecondOfDay,
});
const parseTimeStr = (str, strict) => {
return (strict)
? parseTimeStrict(str)
: parseTimeQuick(str);
};
const parseTimeQuick = (str) => {
const hour = parseInt(str.slice(0, 2), 10);
const minute = parseInt(str.slice(3, 5), 10);
const second = (str.length > 5)
? parseInt(str.slice(6, 8), 10)
: 0;
const nanoseconds = (str.length > 9)
? parseInt(str.slice(9), 10) * Math.pow(10, 9 - (str.length - 9))
: 0;
return [hour, minute, second, nanoseconds];
};
const TimeRegex = /^(\d\d):(\d\d)(?::(\d\d(?:\.(\d{0,9}))?))?$/;
const parseTimeStrict = (str) => {
const match = TimeRegex.exec(str);
if (!match) {
throw Error(`Invalid time: '${str}'; must match HH:MM[:SS[.NNNNNNNNN]]`);
}
const time = [
parseInt(match[1], 10),
parseInt(match[2], 10),
parseInt(match[3] || '0', 10),
parseInt(match[4] || '0', 10) * Math.pow(10, 9 - (match[4]?.length ?? 0)),
];
validateTime(...time);
return time;
};
const validateTime = (hours, minutes, seconds, nanoseconds) => {
if (!Number.isInteger(hours) || !Number.isInteger(minutes) || !Number.isInteger(seconds) || !Number.isInteger(nanoseconds)) {
throw new TypeError(`Invalid hour: ${hours}, minute: ${minutes}, second: ${seconds}, and/or nanosecond: ${nanoseconds}; must be integers`);
}
if (hours < 0 || hours > 23) {
throw RangeError(`Invalid hour: ${hours}; must be in range [0, 23]`);
}
if (minutes < 0 || minutes > 59) {
throw RangeError(`Invalid minute: ${minutes}; must be in range [0, 59]`);
}
if (seconds < 0 || seconds > 59) {
throw RangeError(`Invalid second: ${seconds}; must be in range [0, 59]`);
}
if (nanoseconds < 0 || nanoseconds > 999999999) {
throw RangeError(`Invalid nanosecond: ${nanoseconds}; must be in range [0, 999,999,999]`);
}
};
const ofSecondOfDay = (s) => {
if (typeof s !== 'number') {
throw (0, utils_js_1.mkInvArgsError)('DataAPITime.ofSecondOfDay', [['secondOfDay', 'number']], s);
}
if (!Number.isInteger(s)) {
throw new TypeError(`Invalid number of seconds: ${s}; must be an integer`);
}
if (s < 0 || 86399 < s) {
throw RangeError(`Invalid number of seconds: ${s}; must be in range [0, 86,399]`);
}
const hours = ~~(s / 3600);
s -= hours * 3600;
const minutes = ~~(s / 60);
s -= minutes * 60;
return [hours, minutes, s, 0];
};
const ofNanoOfDay = (ns) => {
if (typeof ns !== 'number') {
throw (0, utils_js_1.mkInvArgsError)('DataAPITime.ofNanoOfDay', [['nanoOfDay', 'number']], ns);
}
if (!Number.isInteger(ns)) {
throw new TypeError(`Invalid number of nanoseconds: ${ns}; must be an integer`);
}
if (ns < 0 || 86399999999999 < ns) {
throw RangeError(`Invalid number of nanoseconds: ${ns}; must be in range [0, 86,399,999,999,999]`);
}
const hours = ~~(ns / 3600000000000);
ns -= hours * 3600000000000;
const minutes = ~~(ns / 60000000000);
ns -= minutes * 60000000000;
const seconds = ~~(ns / 1000000000);
ns -= seconds * 1000000000;
return [hours, minutes, seconds, ns];
};