cassandra-driver
Version:
DataStax Node.js Driver for Apache Cassandra
295 lines (278 loc) • 8.5 kB
JavaScript
/*
* Copyright DataStax, Inc.
*
* 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.
*/
;
const Long = require('long');
const util = require('util');
const utils = require('../utils');
/** @module types */
/**
* @const
* @private
* */
const maxNanos = Long.fromString('86399999999999');
/**
* Nanoseconds in a second
* @const
* @private
* */
const nanoSecInSec = Long.fromNumber(1000000000);
/**
* Nanoseconds in a millisecond
* @const
* @private
* */
const nanoSecInMillis = Long.fromNumber(1000000);
/**
* Milliseconds in day
* @const
* @private
* */
const millisInDay = 86400000;
/**
*
* Creates a new instance of LocalTime.
* @class
* @classdesc A time without a time-zone in the ISO-8601 calendar system, such as 10:30:05.
* <p>
* LocalTime is an immutable date-time object that represents a time, often viewed as hour-minute-second. Time is represented to nanosecond precision. For example, the value "13:45.30.123456789" can be stored in a LocalTime.
* </p>
* @param {Long} totalNanoseconds Total nanoseconds since midnight.
* @constructor
*/
function LocalTime(totalNanoseconds) {
if (!(totalNanoseconds instanceof Long)) {
throw new Error('You must specify a Long value as totalNanoseconds');
}
if (totalNanoseconds.lessThan(Long.ZERO) || totalNanoseconds.greaterThan(maxNanos)) {
throw new Error('Total nanoseconds out of range');
}
this.value = totalNanoseconds;
/**
* Gets the hour component of the time represented by the current instance, a number from 0 to 23.
* @type Number
*/
this.hour = this._getParts()[0];
/**
* Gets the minute component of the time represented by the current instance, a number from 0 to 59.
* @type Number
*/
this.minute = this._getParts()[1];
/**
* Gets the second component of the time represented by the current instance, a number from 0 to 59.
* @type Number
*/
this.second = this._getParts()[2];
/**
* Gets the nanoseconds component of the time represented by the current instance, a number from 0 to 999999999.
* @type Number
*/
this.nanosecond = this._getParts()[3];
}
/**
* Parses an string representation and returns a new LocalDate.
* @param {String} value
* @returns {LocalTime}
*/
LocalTime.fromString = function (value) {
if (typeof value !== 'string') {
throw new Error('Argument type invalid: ' + util.inspect(value));
}
const parts = value.split(':');
let millis = parseInt(parts[0], 10) * 3600000 + parseInt(parts[1], 10) * 60000;
let nanos;
if (parts.length === 3) {
const secParts = parts[2].split('.');
millis += parseInt(secParts[0], 10) * 1000;
if (secParts.length === 2) {
nanos = secParts[1];
//add zeros at the end
nanos = nanos + utils.stringRepeat('0', 9 - nanos.length);
}
}
return LocalTime.fromMilliseconds(millis, parseInt(nanos, 10) || 0);
};
/**
* Uses the current local time (in milliseconds) and the nanoseconds to create a new instance of LocalTime
* @param {Number} [nanoseconds] A Number from 0 to 999,999, representing the time nanosecond portion.
* @returns {LocalTime}
*/
LocalTime.now = function (nanoseconds) {
return LocalTime.fromDate(new Date(), nanoseconds);
};
/**
* Uses the provided local time (in milliseconds) and the nanoseconds to create a new instance of LocalTime
* @param {Date} date Local date portion to extract the time passed since midnight.
* @param {Number} [nanoseconds] A Number from 0 to 999,999, representing the nanosecond time portion.
* @returns {LocalTime}
*/
LocalTime.fromDate = function (date, nanoseconds) {
if (!(date instanceof Date)) {
throw new Error('Not a valid date');
}
//Use the local representation, only the milliseconds portion
const millis = (date.getTime() + date.getTimezoneOffset() * -60000) % millisInDay;
return LocalTime.fromMilliseconds(millis, nanoseconds);
};
/**
* Uses the provided local time (in milliseconds) and the nanoseconds to create a new instance of LocalTime
* @param {Number} milliseconds A Number from 0 to 86,399,999.
* @param {Number} [nanoseconds] A Number from 0 to 999,999, representing the time nanosecond portion.
* @returns {LocalTime}
*/
LocalTime.fromMilliseconds = function (milliseconds, nanoseconds) {
if (typeof nanoseconds !== 'number') {
nanoseconds = 0;
}
return new LocalTime(Long
.fromNumber(milliseconds)
.multiply(nanoSecInMillis)
.add(Long.fromNumber(nanoseconds)));
};
/**
* Creates a new instance of LocalTime from the bytes representation.
* @param {Buffer} value
* @returns {LocalTime}
*/
LocalTime.fromBuffer = function (value) {
if (!(value instanceof Buffer)) {
throw new TypeError('Expected Buffer, obtained ' + util.inspect(value));
}
return new LocalTime(new Long(value.readInt32BE(4), value.readInt32BE(0)));
};
/**
* Compares this LocalTime with the given one.
* @param {LocalTime} other time to compare against.
* @return {number} 0 if they are the same, 1 if the this is greater, and -1
* if the given one is greater.
*/
LocalTime.prototype.compare = function (other) {
return this.value.compare(other.value);
};
/**
* Returns true if the value of the LocalTime instance and other are the same
* @param {LocalTime} other
* @returns {Boolean}
*/
LocalTime.prototype.equals = function (other) {
return ((other instanceof LocalTime)) && this.compare(other) === 0;
};
/**
* Gets the total amount of nanoseconds since midnight for this instance.
* @returns {Long}
*/
LocalTime.prototype.getTotalNanoseconds = function () {
return this.value;
};
LocalTime.prototype.inspect = function () {
return this.constructor.name + ': ' + this.toString();
};
/**
* Returns a big-endian bytes representation of the instance
* @returns {Buffer}
*/
LocalTime.prototype.toBuffer = function () {
const buffer = utils.allocBufferUnsafe(8);
buffer.writeUInt32BE(this.value.getHighBitsUnsigned(), 0);
buffer.writeUInt32BE(this.value.getLowBitsUnsigned(), 4);
return buffer;
};
/**
* Returns the string representation of the instance in the form of hh:MM:ss.ns
* @returns {String}
*/
LocalTime.prototype.toString = function () {
return formatTime(this._getParts());
};
/**
* Gets the string representation of the instance in the form: hh:MM:ss.ns
* @returns {String}
*/
LocalTime.prototype.toJSON = function () {
return this.toString();
};
/**
* @returns {Array.<Number>}
* @ignore
*/
LocalTime.prototype._getParts = function () {
if (!this._partsCache) {
//hours, minutes, seconds and nanos
const parts = [0, 0, 0, 0];
const secs = this.value.div(nanoSecInSec);
//faster modulo
//total nanos
parts[3] = this.value.subtract(secs.multiply(nanoSecInSec)).toNumber();
//seconds
parts[2] = secs.toNumber();
if (parts[2] >= 60) {
//minutes
parts[1] = Math.floor(parts[2] / 60);
parts[2] = parts[2] % 60;
}
if (parts[1] >= 60) {
//hours
parts[0] = Math.floor(parts[1] / 60);
parts[1] = parts[1] % 60;
}
this._partsCache = parts;
}
return this._partsCache;
};
/**
* @param {Array.<Number>} values
* @private
*/
function formatTime(values) {
let result;
if (values[0] < 10) {
result = '0' + values[0] + ':';
}
else {
result = values[0] + ':';
}
if (values[1] < 10) {
result += '0' + values[1] + ':';
}
else {
result += values[1] + ':';
}
if (values[2] < 10) {
result += '0' + values[2];
}
else {
result += values[2];
}
if (values[3] > 0) {
let nanos = values[3].toString();
//nine digits
if (nanos.length < 9) {
nanos = utils.stringRepeat('0', 9 - nanos.length) + nanos;
}
let lastPosition;
for (let i = nanos.length - 1; i > 0; i--) {
if (nanos[i] !== '0') {
break;
}
lastPosition = i;
}
if (lastPosition) {
nanos = nanos.substring(0, lastPosition);
}
result += '.' + nanos;
}
return result;
}
module.exports = LocalTime;