From a14dc1033e95af8fdfa5c69ea703286f276d80f7 Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Wed, 19 Jun 2024 14:01:18 +0200 Subject: [PATCH] [helpers] Fix isInstant & Improve helpers in general (#348) Fixes #346. Signed-off-by: Florian Hotze --- src/helpers.js | 38 ++++++++++---------------------- src/items/time-series.js | 5 +++++ src/time.js | 9 ++++++-- test/quantity.spec.js | 1 + test/time.spec.js | 4 ++-- types/items/time-series.d.ts | 5 +++++ types/items/time-series.d.ts.map | 2 +- types/time.d.ts | 4 ++-- 8 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/helpers.js b/src/helpers.js index 1d4b59cab..a96dcf5ad 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,11 +1,5 @@ // Helper functions used internally across the library -const utils = require('./utils'); -const javaZDT = Java.type('java.time.ZonedDateTime'); -const javaDuration = Java.type('java.time.Duration'); -const javaInstant = Java.type('java.time.Instant'); -const javaTimeSeries = Java.type('org.openhab.core.types.TimeSeries'); - /** * @typedef { import("./items/items").Item } Item * @private @@ -53,7 +47,7 @@ function _toOpenhabPrimitiveType (value) { * Checks whether the given object is an instance of {@link items.Item}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection. + * Checks unique property rawItem, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @returns {boolean} @@ -61,14 +55,14 @@ function _toOpenhabPrimitiveType (value) { */ function _isItem (o) { if (typeof o !== 'object') return false; - return ((o.constructor && o.constructor.name === 'Item') || typeof o.rawItem === 'object'); + return typeof o.rawItem === 'object'; } /** * Checks whether the given object is an instance of {@link Quantity}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection. + * Checks unique property rawQtyType, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @returns {boolean} @@ -76,14 +70,14 @@ function _isItem (o) { */ function _isQuantity (o) { if (typeof o !== 'object') return false; - return ((o.constructor && o.constructor.name === 'Quantity') || typeof o.rawQtyType === 'object'); + return typeof o.rawQtyType === 'object'; } /** * Checks whether the given object is an instance of {@link time.ZonedDateTime}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection. + * Checks _isZonedDateTime property, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @returns {boolean} @@ -91,16 +85,14 @@ function _isQuantity (o) { */ function _isZonedDateTime (o) { if (typeof o !== 'object') return false; - return (((o.constructor && o.constructor.name === 'ZonedDateTime')) || - (!utils.isJsInstanceOfJavaType(o, javaZDT) && typeof o.withFixedOffsetZone === 'function') - ); + return o._isZonedDateTime === true; } /** * Checks whether the given object is an instance of {@link time.Duration}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection. + * Checks _isDuration property, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @returns {boolean} @@ -108,16 +100,14 @@ function _isZonedDateTime (o) { */ function _isDuration (o) { if (typeof o !== 'object') return false; - return (((o.constructor && o.constructor.name === 'Duration')) || - (!utils.isJsInstanceOfJavaType(o, javaDuration) && typeof o.minusDuration === 'function' && typeof o.toNanos === 'function') - ); + return o._isDuration === true; } /** * Checks whether the given object is an instance of {@link time.Instant}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection + * Checks _isInstant property, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @returns {boolean} @@ -125,16 +115,14 @@ function _isDuration (o) { */ function _isInstant (o) { if (typeof o !== 'object') return false; - return (((o.constructor && o.constructor.name === 'Instant')) || - (!utils.isJsInstanceOfJavaType(o, javaInstant) && typeof o.policy === 'string' && typeof o.ofEpochMicro === 'function' && typeof o.ofEpochMilli === 'function' && o.ofEpochSecond === 'function') - ); + return o._isInstant === true; } /** * Checks whether the given object is an instance of {@link items.TimeSeries}. * * To be used when instanceof checks don't work because of circular dependencies or webpack compilation. - * Checks constructor name or unique properties, because constructor name does not work for the webpacked globals injection. + * Checks _isTimeSeries property, because constructor name does not work for the webpacked globals injection. * * @param {*} o * @return {boolean} @@ -142,9 +130,7 @@ function _isInstant (o) { */ function _isTimeSeries (o) { if (typeof o !== 'object') return false; - return (((o.constructor && o.constructor.name === 'TimeSeries')) || - (!utils.isJsInstanceOfJavaType(o, javaTimeSeries) && _isInstant(o.begin) && _isInstant(o.end)) - ); + return o._isTimeSeries === true; } module.exports = { diff --git a/src/items/time-series.js b/src/items/time-series.js index 9713c6330..ed58aae60 100644 --- a/src/items/time-series.js +++ b/src/items/time-series.js @@ -21,6 +21,11 @@ const { _isInstant } = require('../helpers'); * @memberof items */ class TimeSeries { + /** + * @type {boolean} + * @private + */ + _isTimeSeries = true; #states = []; #policy; diff --git a/src/time.js b/src/time.js index fe2f5bd91..7dbe8dd1c 100644 --- a/src/time.js +++ b/src/time.js @@ -454,9 +454,14 @@ time.ZonedDateTime.prototype.toOpenHabString = function () { return this.toString().replace(/\[[^\]]*]$/, ''); }; +// Add fields to allow identification of the object type +time.ZonedDateTime.prototype._isZonedDateTime = true; +time.Duration.prototype._isDuration = true; +time.Instant.prototype._isInstant = true; + module.exports = { ...time, toZDT, - parseString: _parseString, - parseISO8601: _parseISO8601 + _parseString, + _parseISO8601 }; diff --git a/test/quantity.spec.js b/test/quantity.spec.js index 1d9872b81..d37d0df01 100644 --- a/test/quantity.spec.js +++ b/test/quantity.spec.js @@ -5,6 +5,7 @@ const { getQuantity, Quantity, QuantityError, _toBigDecimalOrQtyType, _toQtyType class Item { constructor (rawState) { + this.rawItem = {}; // required for _isItem this.rawState = rawState; } } diff --git a/test/time.spec.js b/test/time.spec.js index b16789df1..e8f2eb867 100644 --- a/test/time.spec.js +++ b/test/time.spec.js @@ -25,7 +25,7 @@ describe('time.js', () => { }); describe('parseString', () => { - const parseString = time.parseString; + const parseString = time._parseString; describe('accepts ISO patterns without the "T" for Blockly', () => { it.each([ @@ -42,7 +42,7 @@ describe('time.js', () => { }); describe('parseISO8601', () => { - const parseISO8601 = time.parseISO8601; + const parseISO8601 = time._parseISO8601; const ZonedDateTime = require('@js-joda/core').ZonedDateTime; describe('parses ISO Date', () => { diff --git a/types/items/time-series.d.ts b/types/items/time-series.d.ts index f51228628..f4d055036 100644 --- a/types/items/time-series.d.ts +++ b/types/items/time-series.d.ts @@ -28,6 +28,11 @@ declare class TimeSeries { * @param {string} policy TimeSeries policy ADD or REPLACE */ constructor(policy: string); + /** + * @type {boolean} + * @private + */ + private _isTimeSeries; /** * The persistence policy of this TimeSeries * diff --git a/types/items/time-series.d.ts.map b/types/items/time-series.d.ts.map index ddf31fc16..e013fac96 100644 --- a/types/items/time-series.d.ts.map +++ b/types/items/time-series.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"time-series.d.ts","sourceRoot":"","sources":["../../src/items/time-series.js"],"names":[],"mappings":";AAGA;;;GAGG;AACH;;;GAGG;AACH;;;GAGG;AAEH;;;;;GAKG;AACH;IAIE;;;;;;;;OAQG;IACH,oBAFW,MAAM,EAKhB;IAED;;;;OAIG;IACH,qBAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;;OAGG;IACH,mBAEC;IAED;;;;;;OAMG;IACH,oBAEC;IAED;;;;;;;;OAQG;IACH,eAJW,CAAC,KAAK,OAAO,GAAC,KAAK,aAAa,GAAC,MAAM,GAAC,IAAI,CAAC,SAC7C,MAAM,GAAC,MAAM,GAAC,QAAQ,YAAU,GAC9B,UAAU,CAMtB;IAED,mBAOC;;CACF;;;;;mBAvGa,OAAO,eAAe,EAAE,OAAO;yBAI/B,OAAO,eAAe,EAAE,aAAa;;;gBAItC,OAAO,aAAa,EAAE,QAAQ"} \ No newline at end of file +{"version":3,"file":"time-series.d.ts","sourceRoot":"","sources":["../../src/items/time-series.js"],"names":[],"mappings":";AAGA;;;GAGG;AACH;;;GAGG;AACH;;;GAGG;AAEH;;;;;GAKG;AACH;IASE;;;;;;;;OAQG;IACH,oBAFW,MAAM,EAKhB;IApBD;;;OAGG;IACH,sBAAqB;IAkBrB;;;;OAIG;IACH,qBAEC;IAED;;;OAGG;IACH,4BAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;;OAGG;IACH,mBAEC;IAED;;;;;;OAMG;IACH,oBAEC;IAED;;;;;;;;OAQG;IACH,eAJW,CAAC,KAAK,OAAO,GAAC,KAAK,aAAa,GAAC,MAAM,GAAC,IAAI,CAAC,SAC7C,MAAM,GAAC,MAAM,GAAC,QAAQ,YAAU,GAC9B,UAAU,CAMtB;IAED,mBAOC;;CACF;;;;;mBA5Ga,OAAO,eAAe,EAAE,OAAO;yBAI/B,OAAO,eAAe,EAAE,aAAa;;;gBAItC,OAAO,aAAa,EAAE,QAAQ"} \ No newline at end of file diff --git a/types/time.d.ts b/types/time.d.ts index a5d583a90..90e73ea4f 100644 --- a/types/time.d.ts +++ b/types/time.d.ts @@ -1,7 +1,7 @@ declare const _exports: { toZDT: typeof toZDT; - parseString: typeof _parseString; - parseISO8601: typeof _parseISO8601; + _parseString: typeof _parseString; + _parseISO8601: typeof _parseISO8601; nativeJs(date: any, zone?: time.ZoneId): time.ZonedDateTime; convert(temporal: time.LocalDate | time.Instant | time.ZonedDateTime | time.LocalDateTime, zone?: time.ZoneId): { toDate: () => Date;