UNPKG

neo4j-driver-core

Version:
564 lines (561 loc) 24.6 kB
"use strict"; /** * Copyright (c) "Neo4j" * Neo4j Sweden AB [https://neo4j.com] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.floorMod = exports.floorDiv = exports.assertValidZoneId = exports.assertValidNanosecond = exports.assertValidSecond = exports.assertValidMinute = exports.assertValidHour = exports.assertValidDay = exports.assertValidMonth = exports.assertValidYear = exports.timeZoneOffsetInSeconds = exports.totalNanoseconds = exports.newDate = exports.toStandardDate = exports.isoStringToStandardDate = exports.dateToIsoString = exports.timeZoneOffsetToIsoString = exports.timeToIsoString = exports.durationToIsoString = exports.dateToEpochDay = exports.localDateTimeToEpochSecond = exports.localTimeToNanoOfDay = exports.normalizeNanosecondsForDuration = exports.normalizeSecondsForDuration = exports.SECONDS_PER_DAY = exports.DAYS_PER_400_YEAR_CYCLE = exports.DAYS_0000_TO_1970 = exports.NANOS_PER_HOUR = exports.NANOS_PER_MINUTE = exports.NANOS_PER_MILLISECOND = exports.NANOS_PER_SECOND = exports.SECONDS_PER_HOUR = exports.SECONDS_PER_MINUTE = exports.MINUTES_PER_HOUR = exports.NANOSECOND_OF_SECOND_RANGE = exports.SECOND_OF_MINUTE_RANGE = exports.MINUTE_OF_HOUR_RANGE = exports.HOUR_OF_DAY_RANGE = exports.DAY_OF_MONTH_RANGE = exports.MONTH_OF_YEAR_RANGE = exports.YEAR_RANGE = void 0; var integer_1 = __importStar(require("../integer")); var error_1 = require("../error"); var util_1 = require("./util"); /* Code in this util should be compatible with code in the database that uses JSR-310 java.time APIs. It is based on a library called ThreeTen (https://github.com/ThreeTen/threetenbp) which was derived from JSR-310 reference implementation previously hosted on GitHub. Code uses `Integer` type everywhere to correctly handle large integer values that are greater than `Number.MAX_SAFE_INTEGER`. Please consult either ThreeTen or js-joda (https://github.com/js-joda/js-joda) when working with the conversion functions. */ var ValueRange = /** @class */ (function () { function ValueRange(min, max) { this._minNumber = min; this._maxNumber = max; this._minInteger = (0, integer_1.int)(min); this._maxInteger = (0, integer_1.int)(max); } ValueRange.prototype.contains = function (value) { if ((0, integer_1.isInt)(value) && value instanceof integer_1.default) { return (value.greaterThanOrEqual(this._minInteger) && value.lessThanOrEqual(this._maxInteger)); } else if (typeof value === 'bigint') { var intValue = (0, integer_1.int)(value); return (intValue.greaterThanOrEqual(this._minInteger) && intValue.lessThanOrEqual(this._maxInteger)); } else { return value >= this._minNumber && value <= this._maxNumber; } }; ValueRange.prototype.toString = function () { return "[".concat(this._minNumber, ", ").concat(this._maxNumber, "]"); }; return ValueRange; }()); exports.YEAR_RANGE = new ValueRange(-999999999, 999999999); exports.MONTH_OF_YEAR_RANGE = new ValueRange(1, 12); exports.DAY_OF_MONTH_RANGE = new ValueRange(1, 31); exports.HOUR_OF_DAY_RANGE = new ValueRange(0, 23); exports.MINUTE_OF_HOUR_RANGE = new ValueRange(0, 59); exports.SECOND_OF_MINUTE_RANGE = new ValueRange(0, 59); exports.NANOSECOND_OF_SECOND_RANGE = new ValueRange(0, 999999999); exports.MINUTES_PER_HOUR = 60; exports.SECONDS_PER_MINUTE = 60; exports.SECONDS_PER_HOUR = exports.SECONDS_PER_MINUTE * exports.MINUTES_PER_HOUR; exports.NANOS_PER_SECOND = 1000000000; exports.NANOS_PER_MILLISECOND = 1000000; exports.NANOS_PER_MINUTE = exports.NANOS_PER_SECOND * exports.SECONDS_PER_MINUTE; exports.NANOS_PER_HOUR = exports.NANOS_PER_MINUTE * exports.MINUTES_PER_HOUR; exports.DAYS_0000_TO_1970 = 719528; exports.DAYS_PER_400_YEAR_CYCLE = 146097; exports.SECONDS_PER_DAY = 86400; function normalizeSecondsForDuration(seconds, nanoseconds) { return (0, integer_1.int)(seconds).add(floorDiv(nanoseconds, exports.NANOS_PER_SECOND)); } exports.normalizeSecondsForDuration = normalizeSecondsForDuration; function normalizeNanosecondsForDuration(nanoseconds) { return floorMod(nanoseconds, exports.NANOS_PER_SECOND); } exports.normalizeNanosecondsForDuration = normalizeNanosecondsForDuration; /** * Converts given local time into a single integer representing this same time in nanoseconds of the day. * @param {Integer|number|string} hour the hour of the local time to convert. * @param {Integer|number|string} minute the minute of the local time to convert. * @param {Integer|number|string} second the second of the local time to convert. * @param {Integer|number|string} nanosecond the nanosecond of the local time to convert. * @return {Integer} nanoseconds representing the given local time. */ function localTimeToNanoOfDay(hour, minute, second, nanosecond) { hour = (0, integer_1.int)(hour); minute = (0, integer_1.int)(minute); second = (0, integer_1.int)(second); nanosecond = (0, integer_1.int)(nanosecond); var totalNanos = hour.multiply(exports.NANOS_PER_HOUR); totalNanos = totalNanos.add(minute.multiply(exports.NANOS_PER_MINUTE)); totalNanos = totalNanos.add(second.multiply(exports.NANOS_PER_SECOND)); return totalNanos.add(nanosecond); } exports.localTimeToNanoOfDay = localTimeToNanoOfDay; /** * Converts given local date time into a single integer representing this same time in epoch seconds UTC. * @param {Integer|number|string} year the year of the local date-time to convert. * @param {Integer|number|string} month the month of the local date-time to convert. * @param {Integer|number|string} day the day of the local date-time to convert. * @param {Integer|number|string} hour the hour of the local date-time to convert. * @param {Integer|number|string} minute the minute of the local date-time to convert. * @param {Integer|number|string} second the second of the local date-time to convert. * @param {Integer|number|string} nanosecond the nanosecond of the local date-time to convert. * @return {Integer} epoch second in UTC representing the given local date time. */ function localDateTimeToEpochSecond(year, month, day, hour, minute, second, nanosecond) { var epochDay = dateToEpochDay(year, month, day); var localTimeSeconds = localTimeToSecondOfDay(hour, minute, second); return epochDay.multiply(exports.SECONDS_PER_DAY).add(localTimeSeconds); } exports.localDateTimeToEpochSecond = localDateTimeToEpochSecond; /** * Converts given local date into a single integer representing it's epoch day. * @param {Integer|number|string} year the year of the local date to convert. * @param {Integer|number|string} month the month of the local date to convert. * @param {Integer|number|string} day the day of the local date to convert. * @return {Integer} epoch day representing the given date. */ function dateToEpochDay(year, month, day) { year = (0, integer_1.int)(year); month = (0, integer_1.int)(month); day = (0, integer_1.int)(day); var epochDay = year.multiply(365); if (year.greaterThanOrEqual(0)) { epochDay = epochDay.add(year .add(3) .div(4) .subtract(year.add(99).div(100)) .add(year.add(399).div(400))); } else { epochDay = epochDay.subtract(year .div(-4) .subtract(year.div(-100)) .add(year.div(-400))); } epochDay = epochDay.add(month .multiply(367) .subtract(362) .div(12)); epochDay = epochDay.add(day.subtract(1)); if (month.greaterThan(2)) { epochDay = epochDay.subtract(1); if (!isLeapYear(year)) { epochDay = epochDay.subtract(1); } } return epochDay.subtract(exports.DAYS_0000_TO_1970); } exports.dateToEpochDay = dateToEpochDay; /** * Format given duration to an ISO 8601 string. * @param {Integer|number|string} months the number of months. * @param {Integer|number|string} days the number of days. * @param {Integer|number|string} seconds the number of seconds. * @param {Integer|number|string} nanoseconds the number of nanoseconds. * @return {string} ISO string that represents given duration. */ function durationToIsoString(months, days, seconds, nanoseconds) { var monthsString = formatNumber(months); var daysString = formatNumber(days); var secondsAndNanosecondsString = formatSecondsAndNanosecondsForDuration(seconds, nanoseconds); return "P".concat(monthsString, "M").concat(daysString, "DT").concat(secondsAndNanosecondsString, "S"); } exports.durationToIsoString = durationToIsoString; /** * Formats given time to an ISO 8601 string. * @param {Integer|number|string} hour the hour value. * @param {Integer|number|string} minute the minute value. * @param {Integer|number|string} second the second value. * @param {Integer|number|string} nanosecond the nanosecond value. * @return {string} ISO string that represents given time. */ function timeToIsoString(hour, minute, second, nanosecond) { var hourString = formatNumber(hour, 2); var minuteString = formatNumber(minute, 2); var secondString = formatNumber(second, 2); var nanosecondString = formatNanosecond(nanosecond); return "".concat(hourString, ":").concat(minuteString, ":").concat(secondString).concat(nanosecondString); } exports.timeToIsoString = timeToIsoString; /** * Formats given time zone offset in seconds to string representation like '±HH:MM', '±HH:MM:SS' or 'Z' for UTC. * @param {Integer|number|string} offsetSeconds the offset in seconds. * @return {string} ISO string that represents given offset. */ function timeZoneOffsetToIsoString(offsetSeconds) { offsetSeconds = (0, integer_1.int)(offsetSeconds); if (offsetSeconds.equals(0)) { return 'Z'; } var isNegative = offsetSeconds.isNegative(); if (isNegative) { offsetSeconds = offsetSeconds.multiply(-1); } var signPrefix = isNegative ? '-' : '+'; var hours = formatNumber(offsetSeconds.div(exports.SECONDS_PER_HOUR), 2); var minutes = formatNumber(offsetSeconds.div(exports.SECONDS_PER_MINUTE).modulo(exports.MINUTES_PER_HOUR), 2); var secondsValue = offsetSeconds.modulo(exports.SECONDS_PER_MINUTE); var seconds = secondsValue.equals(0) ? null : formatNumber(secondsValue, 2); return seconds != null ? "".concat(signPrefix).concat(hours, ":").concat(minutes, ":").concat(seconds) : "".concat(signPrefix).concat(hours, ":").concat(minutes); } exports.timeZoneOffsetToIsoString = timeZoneOffsetToIsoString; /** * Formats given date to an ISO 8601 string. * @param {Integer|number|string} year the date year. * @param {Integer|number|string} month the date month. * @param {Integer|number|string} day the date day. * @return {string} ISO string that represents given date. */ function dateToIsoString(year, month, day) { var yearString = formatYear(year); var monthString = formatNumber(month, 2); var dayString = formatNumber(day, 2); return "".concat(yearString, "-").concat(monthString, "-").concat(dayString); } exports.dateToIsoString = dateToIsoString; /** * Convert the given iso date string to a JavaScript Date object * * @param {string} isoString The iso date string * @returns {Date} the date */ function isoStringToStandardDate(isoString) { return new Date(isoString); } exports.isoStringToStandardDate = isoStringToStandardDate; /** * Convert the given utc timestamp to a JavaScript Date object * * @param {number} utc Timestamp in UTC * @returns {Date} the date */ function toStandardDate(utc) { return new Date(utc); } exports.toStandardDate = toStandardDate; /** * Shortcut for creating a new StandardDate * @param date * @returns {Date} the standard date */ function newDate(date) { return new Date(date); } exports.newDate = newDate; /** * Get the total number of nanoseconds from the milliseconds of the given standard JavaScript date and optional nanosecond part. * @param {global.Date} standardDate the standard JavaScript date. * @param {Integer|number|bigint|undefined} nanoseconds the optional number of nanoseconds. * @return {Integer|number|bigint} the total amount of nanoseconds. */ function totalNanoseconds(standardDate, nanoseconds) { nanoseconds = nanoseconds !== null && nanoseconds !== void 0 ? nanoseconds : 0; var nanosFromMillis = standardDate.getMilliseconds() * exports.NANOS_PER_MILLISECOND; return add(nanoseconds, nanosFromMillis); } exports.totalNanoseconds = totalNanoseconds; /** * Get the time zone offset in seconds from the given standard JavaScript date. * * <b>Implementation note:</b> * Time zone offset returned by the standard JavaScript date is the difference, in minutes, from local time to UTC. * So positive value means offset is behind UTC and negative value means it is ahead. * For Neo4j temporal types, like `Time` or `DateTime` offset is in seconds and represents difference from UTC to local time. * This is different from standard JavaScript dates and that's why implementation negates the returned value. * * @param {global.Date} standardDate the standard JavaScript date. * @return {number} the time zone offset in seconds. */ function timeZoneOffsetInSeconds(standardDate) { var secondsPortion = standardDate.getSeconds() >= standardDate.getUTCSeconds() ? standardDate.getSeconds() - standardDate.getUTCSeconds() : standardDate.getSeconds() - standardDate.getUTCSeconds() + 60; var offsetInMinutes = standardDate.getTimezoneOffset(); if (offsetInMinutes === 0) { return 0 + secondsPortion; } return -1 * offsetInMinutes * exports.SECONDS_PER_MINUTE + secondsPortion; } exports.timeZoneOffsetInSeconds = timeZoneOffsetInSeconds; /** * Assert that the year value is valid. * @param {Integer|number} year the value to check. * @return {Integer|number} the value of the year if it is valid. Exception is thrown otherwise. */ function assertValidYear(year) { return assertValidTemporalValue(year, exports.YEAR_RANGE, 'Year'); } exports.assertValidYear = assertValidYear; /** * Assert that the month value is valid. * @param {Integer|number} month the value to check. * @return {Integer|number} the value of the month if it is valid. Exception is thrown otherwise. */ function assertValidMonth(month) { return assertValidTemporalValue(month, exports.MONTH_OF_YEAR_RANGE, 'Month'); } exports.assertValidMonth = assertValidMonth; /** * Assert that the day value is valid. * @param {Integer|number} day the value to check. * @return {Integer|number} the value of the day if it is valid. Exception is thrown otherwise. */ function assertValidDay(day) { return assertValidTemporalValue(day, exports.DAY_OF_MONTH_RANGE, 'Day'); } exports.assertValidDay = assertValidDay; /** * Assert that the hour value is valid. * @param {Integer|number} hour the value to check. * @return {Integer|number} the value of the hour if it is valid. Exception is thrown otherwise. */ function assertValidHour(hour) { return assertValidTemporalValue(hour, exports.HOUR_OF_DAY_RANGE, 'Hour'); } exports.assertValidHour = assertValidHour; /** * Assert that the minute value is valid. * @param {Integer|number} minute the value to check. * @return {Integer|number} the value of the minute if it is valid. Exception is thrown otherwise. */ function assertValidMinute(minute) { return assertValidTemporalValue(minute, exports.MINUTE_OF_HOUR_RANGE, 'Minute'); } exports.assertValidMinute = assertValidMinute; /** * Assert that the second value is valid. * @param {Integer|number} second the value to check. * @return {Integer|number} the value of the second if it is valid. Exception is thrown otherwise. */ function assertValidSecond(second) { return assertValidTemporalValue(second, exports.SECOND_OF_MINUTE_RANGE, 'Second'); } exports.assertValidSecond = assertValidSecond; /** * Assert that the nanosecond value is valid. * @param {Integer|number} nanosecond the value to check. * @return {Integer|number} the value of the nanosecond if it is valid. Exception is thrown otherwise. */ function assertValidNanosecond(nanosecond) { return assertValidTemporalValue(nanosecond, exports.NANOSECOND_OF_SECOND_RANGE, 'Nanosecond'); } exports.assertValidNanosecond = assertValidNanosecond; var timeZoneValidityCache = new Map(); var newInvalidZoneIdError = function (zoneId, fieldName) { return (0, error_1.newError)("".concat(fieldName, " is expected to be a valid ZoneId but was: \"").concat(zoneId, "\"")); }; function assertValidZoneId(fieldName, zoneId) { var cachedResult = timeZoneValidityCache.get(zoneId); if (cachedResult === true) { return; } if (cachedResult === false) { throw newInvalidZoneIdError(zoneId, fieldName); } try { Intl.DateTimeFormat(undefined, { timeZone: zoneId }); timeZoneValidityCache.set(zoneId, true); } catch (e) { timeZoneValidityCache.set(zoneId, false); throw newInvalidZoneIdError(zoneId, fieldName); } } exports.assertValidZoneId = assertValidZoneId; /** * Check if the given value is of expected type and is in the expected range. * @param {Integer|number} value the value to check. * @param {ValueRange} range the range. * @param {string} name the name of the value. * @return {Integer|number} the value if valid. Exception is thrown otherwise. */ function assertValidTemporalValue(value, range, name) { (0, util_1.assertNumberOrInteger)(value, name); if (!range.contains(value)) { throw (0, error_1.newError)("".concat(name, " is expected to be in range ").concat(range.toString(), " but was: ").concat(value.toString())); } return value; } /** * Converts given local time into a single integer representing this same time in seconds of the day. Nanoseconds are skipped. * @param {Integer|number|string} hour the hour of the local time. * @param {Integer|number|string} minute the minute of the local time. * @param {Integer|number|string} second the second of the local time. * @return {Integer} seconds representing the given local time. */ function localTimeToSecondOfDay(hour, minute, second) { hour = (0, integer_1.int)(hour); minute = (0, integer_1.int)(minute); second = (0, integer_1.int)(second); var totalSeconds = hour.multiply(exports.SECONDS_PER_HOUR); totalSeconds = totalSeconds.add(minute.multiply(exports.SECONDS_PER_MINUTE)); return totalSeconds.add(second); } /** * Check if given year is a leap year. Uses algorithm described here {@link https://en.wikipedia.org/wiki/Leap_year#Algorithm}. * @param {Integer|number|string} year the year to check. Will be converted to {@link Integer} for all calculations. * @return {boolean} `true` if given year is a leap year, `false` otherwise. */ function isLeapYear(year) { year = (0, integer_1.int)(year); if (!year.modulo(4).equals(0)) { return false; } else if (!year.modulo(100).equals(0)) { return true; } else if (!year.modulo(400).equals(0)) { return false; } else { return true; } } /** * @param {Integer|number|string} x the divident. * @param {Integer|number|string} y the divisor. * @return {Integer} the result. */ function floorDiv(x, y) { x = (0, integer_1.int)(x); y = (0, integer_1.int)(y); var result = x.div(y); if (x.isPositive() !== y.isPositive() && result.multiply(y).notEquals(x)) { result = result.subtract(1); } return result; } exports.floorDiv = floorDiv; /** * @param {Integer|number|string} x the divident. * @param {Integer|number|string} y the divisor. * @return {Integer} the result. */ function floorMod(x, y) { x = (0, integer_1.int)(x); y = (0, integer_1.int)(y); return x.subtract(floorDiv(x, y).multiply(y)); } exports.floorMod = floorMod; /** * @param {Integer|number|string} seconds the number of seconds to format. * @param {Integer|number|string} nanoseconds the number of nanoseconds to format. * @return {string} formatted value. */ function formatSecondsAndNanosecondsForDuration(seconds, nanoseconds) { seconds = (0, integer_1.int)(seconds); nanoseconds = (0, integer_1.int)(nanoseconds); var secondsString; var nanosecondsString; var secondsNegative = seconds.isNegative(); var nanosecondsGreaterThanZero = nanoseconds.greaterThan(0); if (secondsNegative && nanosecondsGreaterThanZero) { if (seconds.equals(-1)) { secondsString = '-0'; } else { secondsString = seconds.add(1).toString(); } } else { secondsString = seconds.toString(); } if (nanosecondsGreaterThanZero) { if (secondsNegative) { nanosecondsString = formatNanosecond(nanoseconds .negate() .add(2 * exports.NANOS_PER_SECOND) .modulo(exports.NANOS_PER_SECOND)); } else { nanosecondsString = formatNanosecond(nanoseconds.add(exports.NANOS_PER_SECOND).modulo(exports.NANOS_PER_SECOND)); } } return nanosecondsString != null ? secondsString + nanosecondsString : secondsString; } /** * @param {Integer|number|string} value the number of nanoseconds to format. * @return {string} formatted and possibly left-padded nanoseconds part as string. */ function formatNanosecond(value) { value = (0, integer_1.int)(value); return value.equals(0) ? '' : '.' + formatNumber(value, 9); } /** * * @param {Integer|number|string} year The year to be formatted * @return {string} formatted year */ function formatYear(year) { var yearInteger = (0, integer_1.int)(year); if (yearInteger.isNegative() || yearInteger.greaterThan(9999)) { return formatNumber(yearInteger, 6, { usePositiveSign: true }); } return formatNumber(yearInteger, 4); } /** * @param {Integer|number|string} num the number to format. * @param {number} [stringLength=undefined] the string length to left-pad to. * @return {string} formatted and possibly left-padded number as string. */ function formatNumber(num, stringLength, params) { num = (0, integer_1.int)(num); var isNegative = num.isNegative(); if (isNegative) { num = num.negate(); } var numString = num.toString(); if (stringLength != null) { // left pad the string with zeroes while (numString.length < stringLength) { numString = '0' + numString; } } if (isNegative) { return '-' + numString; } else if ((params === null || params === void 0 ? void 0 : params.usePositiveSign) === true) { return '+' + numString; } return numString; } function add(x, y) { if (x instanceof integer_1.default) { return x.add(y); } else if (typeof x === 'bigint') { return x + BigInt(y); } return x + y; }