Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

node-opcua-date-time

Package Overview
Dependencies
Maintainers
1
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-opcua-date-time - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

test/test_clock_performance.js

13

package.json
{
"name": "node-opcua-date-time",
"main": "./src/date_time.js",
"version": "0.3.0",
"version": "0.4.0",
"description": "pure nodejs OPCUA SDK - module -date-time",

@@ -10,9 +10,10 @@ "scripts": {

"dependencies": {
"node-opcua-assert": "^0.3.0",
"underscore": "^1.8.3"
"long": "^4.0.0",
"node-opcua-assert": "^0.4.0",
"underscore": "^1.9.0"
},
"devDependencies": {
"bignumber.js": "^6.0.0",
"node-opcua-benchmarker": "^0.3.0",
"node-opcua-binary-stream": "^0.3.0",
"bignumber.js": "^7.2.1",
"node-opcua-benchmarker": "^0.4.0",
"node-opcua-binary-stream": "^0.4.0",
"should": "13.2.1"

@@ -19,0 +20,0 @@ },

"use strict";
const assert = require("node-opcua-assert").assert;
const _ = require("underscore");
const Long = require("long");

@@ -31,9 +31,4 @@ const offset_factor_1601 = (function () {

const F = 0x100000000;
const A = factor / F;
const B = offset * A;
const oh = Math.floor(offset / F);
const ol = offset % F;
const fl = factor % F;
const F_div_factor = (F / factor);
const offsetLong = Long.fromNumber(offset,true);
const factorLong = Long.fromNumber(factor,true);

@@ -77,8 +72,12 @@ // Extracted from OpcUA Spec v1.02 : part 6:

* @param date {Date}
* @param picoseconds {Number} : represent the portion of the date that cannot be managed by the javascript Date object
*
* @returns {[high,low]}
*/
function bn_dateToHundredNanoSecondFrom1601_fast(date) {
function bn_dateToHundredNanoSecondFrom1601_fast(date, picoseconds) {
assert(date instanceof Date);
if (date.high_low) {
return date.high_low;
return date.high_low;
}

@@ -90,30 +89,11 @@

const t = date.getTime(); // number of milliseconds since since 1 January 1970 00:00:00 UTC.
const excess_100nano_second = (picoseconds !== undefined) ? Math.floor(picoseconds / 100000) : 0;
//Note:
// The number of 100-nano since 1 Jan 1601 is given by the formula :
//
// value_64 = (t + offset ) * factor;
//
// However this number is too large and shall be converted to a 64 bits integer
//
// Let say that value_64 = (value_h * 0xFFFFFFFF ) + value_l, where value_h and value_l are two 32bits integers.
//
// Let say F = 0x100000000
// (value_h * F ) + value_l = (t+ offset)*factor;
//
// value_h = (t+ offset)*factor // F;
// value_l = (t+ offset)*factor % F;
//
// value_h = floor(t * factor / F + offset*factor / F)
// floor(t * A + B)
//
// value_l = ((t % F + offset % F) * (factor % F) )% F
// value_l = ((t % F + ol ) * fl )% F
const tL = Long.fromNumber(t,false);
const a = tL.add(offsetLong).multiply(factorLong).add(excess_100nano_second);
const value_h = Math.floor(t * A + B);
let value_l = ((t % F + ol) * fl) % F;
value_l = (value_l + F) % F;
const high_low = [value_h, value_l];
date.high_low = high_low;
return high_low;
date.high_low = [a.getHighBits(),a.getLowBits()];
date.picoseconds = excess_100nano_second * 10000 + picoseconds;
return date.high_low;
}

@@ -123,23 +103,20 @@

function bn_hundredNanoSecondFrom1601ToDate_fast(high, low) {
//xx assert(_.isFinite(high), _.isFinite(low));
exports.bn_dateToHundredNanoSecondFrom1601Excess = function bn_dateToHundredNanoSecondFrom1601Excess(data,picoseconds)
{
// 100 nano seconds = 100 x 1000 picoseconds
return (picoseconds !== undefined) ? picoseconds % 100000 :0 ;
// (h * F + l)/f - o=
// h / f * F + l/f - o=
//
// h = ((h div f)* f + h % f)
// h/f = (h div f) + (h % f) /f
// h/f * F = (h div f)*F + (h % f) * F/f
// o = oh * F + ol
const value1 = (Math.floor(high / factor) - oh) * F + Math.floor((high % factor) * F_div_factor + low / factor) - ol;
};
function bn_hundredNanoSecondFrom1601ToDate_fast(high, low , picoseconds) {
assert(low !== undefined);
// value_64 / factor - offset = t
const l= new Long(low,high,/*unsigned*/true);
const value1 = l.div(factor).toNumber()-offset;
const date = new Date(value1);
// enrich the date
const excess_100nano_in_pico = l.mod(10000).mul(100000).toNumber();
date.high_low = [high,low];
//xxObject.defineProperty(date, "high_low", {
//xx get: function () {
//xx return [high, low];
//xx }, enumerable: false
//xx});
// picosecond will contains un-decoded 100 nanoseconds => 10 x 100 nanoseconds = 1 microsecond
date.picoseconds = excess_100nano_in_pico + ((picoseconds !=null )? picoseconds : 0);
return date;

@@ -153,9 +130,13 @@ }

let last_picoseconds = 0;
function getCurrentClock() {
let small_tick_picosecond = 1000 * 100; // 100 nano second in picoseconds
/**
*
* @return {{timestamp: *, picoseconds: number}}
*/
function getCurrentClockWithJavascriptDate() {
const now = new Date();
if (last_now_date && now.getTime() === last_now_date.getTime()) {
last_picoseconds += 1;
last_picoseconds += small_tick_picosecond; // add "100 nano" second which is hte resolution of OPCUA DateTime
} else {
last_picoseconds = 1;
last_picoseconds = 0;
last_now_date = now;

@@ -169,2 +150,28 @@ }

const origin = process.hrtime();
const refTime = Date.now();
const g_clock = {
tick: [0,0],
timestamp: new Date(),
picoseconds: 0
};
// make sure we get a pointer to the actual process.hrtime, just in case it get overridden by some library (such as sinon)
const hrtime = process.hrtime;
function getCurrentClockWithProcessHRTime() {
g_clock.tick = hrtime(origin); // [seconds, nanoseconds]
const milliseconds = g_clock.tick[0] * 1000 + Math.floor(g_clock.tick[1] / 1000000) + refTime;
const picoseconds = (g_clock.tick[1] % 1000000) * 1000;
// display drift in seconds :
// console.log(g_clock.tick[0] - Math.floor((Date.now()-refTime) / 1000));
g_clock.timestamp =new Date(milliseconds);
g_clock.picoseconds= picoseconds;
return g_clock;
}
const getCurrentClock = ( process.hrtime && true) ? getCurrentClockWithProcessHRTime: getCurrentClockWithJavascriptDate;
function coerceClock(timestamp, picoseconds) {

@@ -171,0 +178,0 @@ if (timestamp) {

@@ -38,7 +38,14 @@ "use strict";

const MAXUINT32 = 4294967295; // 2**32 - 1
exports.encodeDateTime = function (date, stream) {
/**
*
* @param date {Date}
* @param picoseconds {null|number} {number of pico seconds to improve javascript date... }
* @param stream
*/
exports.encodeHighAccuracyDateTime = function (date,picoseconds, stream) {
if (!date) {
stream.writeUInt32(0);
stream.writeUInt32(0);
stream.writeUInt32(picoseconds % 100000);
return;

@@ -50,24 +57,34 @@ }

assert(date instanceof Date);
let hl = bn_dateToHundredNanoSecondFrom1601(date);
let hl = bn_dateToHundredNanoSecondFrom1601(date,picoseconds);
let hi = hl[0];
let lo = hl[1];
// make sure that date are not lower than expected limit
if (hi<0 || lo<0) {
hi=0;lo=0;
}
if (hi <0 || lo<0 || hi > MAXUINT32 || lo > MAXUINT32 ) {
hl = bn_dateToHundredNanoSecondFrom1601(date);
throw new Error("INVALID " + hi + " "+lo + " "+date.toUTCString());
}
stream.writeUInt32(lo);
stream.writeUInt32(hi);
//xx make sure that date are not lower than expected limit
//xx if (hi<0 || lo<0) {
//xx hi=0;lo=0;
//xx }
//xx if (hi <0 || lo<0 || hi > MAXUINT32 || lo > MAXUINT32 ) {
//xx hl = bn_dateToHundredNanoSecondFrom1601(date);
//xx throw new Error("INVALID " + hi + " "+lo + " "+date.toUTCString());
//x}
stream.writeInteger(lo);
stream.writeInteger(hi);
//xx assert(date.toString() === bn_hundredNanoSecondFrom1601ToDate(hi, lo).toString());
};
exports.encodeDateTime = function (date, stream) {
exports.encodeHighAccuracyDateTime(date,0,stream);
};
/**
*
* @param stream
* @returns {Date}
*/
exports.decodeDateTime = function (stream) {
const lo = stream.readUInt32();
const hi = stream.readUInt32();
const lo = stream.readInteger();
const hi = stream.readInteger();
return bn_hundredNanoSecondFrom1601ToDate(hi, lo);
};
exports.decodeHighAccuracyDateTime = exports.decodeDateTime;

@@ -74,0 +91,0 @@

@@ -13,3 +13,5 @@ "use strict";

const factor = offset_factor_1601[1];
const Long = require("long");
function isValidUInt32(value) {

@@ -21,4 +23,13 @@ if (!_.isFinite(value)) {

}
function isValidInt32(value) {
if (!_.isFinite(value)) {
return false;
}
value.should.be.greaterThan(-Math.pow(2,31)-1);
value.should.be.lessThan(Math.pow(2,31)+1);
return true;
}
// deprecated (inaccurate)

@@ -47,4 +58,4 @@ const assert = require("node-opcua-assert").assert;

const date = new Date(2014, 0, 1);
const nano = deprecated_dateToHundredNanoSecondFrom1601(date);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(nano);
const hundred_nano = deprecated_dateToHundredNanoSecondFrom1601(date);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(hundred_nano);
date2.toString().should.equal(date.toString());

@@ -56,4 +67,4 @@

const date = new Date(Date.UTC(1601, 0, 1, 0, 0));
const nano = deprecated_dateToHundredNanoSecondFrom1601(date);
nano.should.equal(0);
const hundred_nano = deprecated_dateToHundredNanoSecondFrom1601(date);
hundred_nano.should.equal(0);
});

@@ -64,5 +75,5 @@

const date = new Date(Date.UTC(1601, 0, 2, 0, 0));
const nano = deprecated_dateToHundredNanoSecondFrom1601(date);
nano.should.equal(24 * 60 * 60 * 1000 * 10000);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(nano);
const hundred_nano = deprecated_dateToHundredNanoSecondFrom1601(date);
hundred_nano.should.equal(24 * 60 * 60 * 1000 * 10000);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(hundred_nano);
date2.toString().should.equal(date.toString());

@@ -74,4 +85,4 @@ });

const date = new Date(1789, 6, 14, 19, 47);
const nano = deprecated_dateToHundredNanoSecondFrom1601(date);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(nano);
const hundred_nano = deprecated_dateToHundredNanoSecondFrom1601(date);
const date2 = deprecated_hundredNanoSecondFrom1601ToDate(hundred_nano);

@@ -105,6 +116,6 @@ date2.toString().should.equal(date.toString());

const date = new Date(Date.UTC(1601, 0, 2, 0, 0, 0));
const nano = date_time.bn_dateToHundredNanoSecondFrom1601(date);
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date);
const value = 24 * 60 * 60 * 1000 * 10000; // number of nanosecond in a single day
nano[0].should.equal(Math.floor(value / 0x100000000));
nano[1].should.equal(value % 0x100000000);
hundred_nano[0].should.equal(Math.floor(value / 0x100000000));
hundred_nano[1].should.equal(value % 0x100000000);
});

@@ -114,3 +125,3 @@

const buf = new Buffer(8);
const buf = Buffer.alloc(8);
buf.writeUInt32LE(0xd353c292, 0);

@@ -182,5 +193,5 @@ buf.writeUInt32LE(0x01cef70c, 4);

const date = new Date(2014, 0, 1);
const nano1 = bn_dateToHundredNanoSecondFrom1601_big_number(date);
const nano2 = date_time.bn_dateToHundredNanoSecondFrom1601(date);
nano1.should.eql(nano2);
const hundred_nano1 = bn_dateToHundredNanoSecondFrom1601_big_number(date);
const hundred_nano2 = date_time.bn_dateToHundredNanoSecondFrom1601(date);
hundred_nano1.should.eql(hundred_nano2);
});

@@ -221,11 +232,11 @@

const date = new Date(2014, 0, 1);
const nano = date_time.bn_dateToHundredNanoSecondFrom1601(date);
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date);
const bench = new Benchmarker();
bench.add('bn_hundredNanoSecondFrom1601ToDate_safe', function () {
bn_hundredNanoSecondFrom1601ToDate_big_number(nano[0], nano[1]);
bn_hundredNanoSecondFrom1601ToDate_big_number(hundred_nano[0], hundred_nano[1]);
})
.add('bn_hundredNanoSecondFrom1601ToDate_fast', function () {
date_time.bn_hundredNanoSecondFrom1601ToDate(nano[0], nano[1]);
date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0], hundred_nano[1]);
})

@@ -273,3 +284,3 @@ .on('cycle', function (message) {

isValidUInt32(hl[0]).should.eql(true);
isValidUInt32(hl[1]).should.eql(true);
isValidInt32(hl[1]).should.eql(true);
ec.encodeDateTime(date, bs);

@@ -292,6 +303,5 @@ bs.rewind();

const verif = bn_dateToHundredNanoSecondFrom1601_big_number(date);
//xx console.log(date.toUTCString(), "0x0"+nano[0].toString(16),"0x"+nano[1].toString(16),nano,verif[0].toString(16),verif[1].toString(16));
console.log(date.toUTCString(), "0x0"+nano[0].toString(16),"0x"+nano[1].toString(16),nano,verif[0].toString(16),verif[1].toString(16));
nano[0].should.equal(0x019DB1DE); // hi
nano[1].should.equal(0xD53E8000); // lo
nano[1].should.equal(-0x2ac18000); // lo
});

@@ -365,2 +375,157 @@

});
it("should convert a time with picoseconds into 64bit work",function() {
{
const date = new Date(Date.UTC(1601, 0, 1, 0, 0, 0));
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date);
hundred_nano[0].should.equal(0);
hundred_nano[1].should.equal(0);
}
{
const date = new Date(Date.UTC(1601, 0, 1, 0, 0, 0));
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, 100 * 1000);
hundred_nano[0].should.equal(0); // hi
hundred_nano[1].should.equal(1); // lo
}
{
const date = new Date(Date.UTC(1601, 0, 1, 0, 0, 0));
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, 1 * 1000 * 1000);
hundred_nano[0].should.equal(0); // hi
hundred_nano[1].should.equal(10); // lo 1ms = 10 * 100 hundred_nanosecond
const dateVerif = date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0], hundred_nano[1]);
dateVerif.picoseconds.should.eql(1000000);
dateVerif.getTime().should.eql(date.getTime());
}
{
const date = new Date(Date.UTC(1601, 0, 1, 0, 0, 1)); // 1 seconds
// 90 100xnano seconds = 9000 hundred_nano = 9000x 1000 picon
const picoseconds = 9000 * 1000 + 5000;
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
hundred_nano[0].should.equal(0); // hi
// 1 seconds = 1000 ms = 1000x1000 microsecond = 1000x1000x10 hundred_nanoseconds
hundred_nano[1].should.equal(10000000 + 90); // lo 1ms = 10 * 100 hundred_nanosecond
const excessPicoSeconds = date_time.bn_dateToHundredNanoSecondFrom1601Excess(date, picoseconds);
excessPicoSeconds.should.eql(5000);
const dateVerif = date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0], hundred_nano[1]);
dateVerif.picoseconds.should.eql(9000 * 1000);
dateVerif.getTime().should.eql(date.getTime());
}
});
it("ZZ should convert a time with picoseconds into 64bit work",function() {
const date = new Date(Date.UTC(1601, 0, 1, 0,0,12,345));
const picoseconds = 987654320;
/// 9876 hundred nano-seonds and 54320 picoseconds
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
hundred_nano[0].should.equal(0); // hi
// 1 seconds = 1000 ms = 1000x1000 microsecond = 1000x1000x10 nanoseconds
hundred_nano[1].should.equal(123459876); // lo 1ms = 10 * 100 nanosecond
const excessPicoSeconds = date_time.bn_dateToHundredNanoSecondFrom1601Excess(date,picoseconds);
excessPicoSeconds.should.eql(54320);
const dateVerif = date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0],hundred_nano[1],excessPicoSeconds);
dateVerif.picoseconds.should.eql(987654320);
dateVerif.getTime().should.eql(date.getTime());
});
it("ZZ1 should convert a time with picoseconds",function() {
//const date = new Date(Date.UTC(2018,1,23,12,34,56,789));
const date = new Date(Date.UTC(1601, 0, 1, 0,0,12,345));
date.setTime(date.getTime() + Math.pow(2,33));
const picoseconds = 987654320;
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
//nano[0].should.equal(0); // hi
// 1 seconds = 1000 ms = 1000x1000 microsecond = 1000x1000x10 nanoseconds
(hundred_nano[1] % 10000000).should.equal(3459876); // lo 1ms = 10 * 100 nanosecond
});
it("ZZ2 should convert a time with picoseconds",function() {
//const date = new Date(Date.UTC(2018,1,23,12,34,56,789));
const date = new Date(Date.UTC(1601, 0, 1, 0,0,12,345));
date.setTime(date.getTime() + Math.pow(2,33));
const picoseconds = 987654320;
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
hundred_nano[0].should.equal(20 * 1000); // hi
// 1 seconds = 1000 ms = 1000x1000 microsecond = 1000x1000x10 nanoseconds
(hundred_nano[1] % 10000000).should.equal(3459876); // lo 1ms = 10 * 100 nanosecond
});
it("ZZ3 should convert a time with picoseconds",function() {
const date = new Date(Date.UTC(2018,1,23,12,34,56,789));
const picoseconds = 50000000;
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
// 1 seconds = 1000 ms = 1000x1000 microsecond = 1000x1000x10 hundred nanoseconds
const hnl = new Long(hundred_nano[1],hundred_nano[0],true);
hnl.mod(10*1000*1000).toNumber().should.equal(7890500); // lo 1ms = 10 * 100 nanosecond
});
it("ZZ12",function() {
const date = new Date(Date.UTC(2018,1,23,18,54,12,345));
const picoseconds= 12345670;
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(date, picoseconds);
const excess = date_time.bn_dateToHundredNanoSecondFrom1601Excess(date,picoseconds);
const dateVerif = date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0],hundred_nano[1],excess);
dateVerif.picoseconds.should.have.type("number");
const hundred_nanoVerif = date_time.bn_dateToHundredNanoSecondFrom1601(dateVerif, dateVerif.picoseconds);
hundred_nano.should.eql(hundred_nanoVerif);
dateVerif.getTime().should.eql(date.getTime());
// encode decode
const stream = new BinaryStream(1000);
ec.encodeDateTime(date,stream);
stream.rewind();
const dateVerif1 = ec.decodeDateTime(stream);
dateVerif1.getTime().should.eql(date.getTime());
});
const getCurrentClock= require("../src/date_time").getCurrentClock;
it("should convert a time to 100nano and back",function() {
for (let i= 0;i<10000;i++) {
const clock = getCurrentClock();
clock.picoseconds.should.have.type("number");
//Xx console.log(clock);
const hundred_nano = date_time.bn_dateToHundredNanoSecondFrom1601(clock.timestamp, clock.picoseconds);
//Xx console.log(+clock.timestamp,clock.picoseconds);
//Xx console.log(nano);
const dateVerif = date_time.bn_hundredNanoSecondFrom1601ToDate(hundred_nano[0],hundred_nano[1]);
dateVerif.picoseconds.should.have.type("number");
const hundred_nanoVerif = date_time.bn_dateToHundredNanoSecondFrom1601(dateVerif, dateVerif.picoseconds);
hundred_nano.should.eql(hundred_nanoVerif);
dateVerif.getTime().should.eql(clock.timestamp.getTime());
//xx (clock.picoseconds % 10000).should.eql((dateVerif.picoseconds% 10000));
}
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc