Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[time] Default to system timezone in toZDT if none is explicitely set #307

Merged
merged 9 commits into from
Dec 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ The following rules are used during the conversion:
| `"kk:mm[:ss][ ]a"` (12 hour time) | today's date with the time indicated, the space between the time and am/pm and seconds are optional | `time.toZDT('1:23:45 PM');` |
| [ISO 8601 Duration](https://en.wikipedia.org/wiki/ISO_8601#Durations) String | added to `now` | `time.toZDT('PT1H4M6.789S');` |

If no time zone is explicitly set, the system default time zone is used.
When a type or string that cannot be handled is encountered, an error is thrown.

#### `toToday()`
Expand Down
21 changes: 15 additions & 6 deletions test/time.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const time = require('../time');
const { ZonedDateTime } = require('@js-joda/core');
const { ZonedDateTime, ZoneId } = require('@js-joda/core');

jest.mock('../items', () => ({
Item: new Object() // eslint-disable-line no-new-object
Expand Down Expand Up @@ -67,13 +67,9 @@ describe('time.js', () => {
});
});

describe('parses ISO DateTime with zone offset and/or time/zone', () => {
describe('parses ISO DateTime with zone offset and timezone', () => {
it.each([
['YYYY-MM-DDThh:mm:ss.f+HH:mm[SYSTEM]', '2016-03-18T12:38:23.561+01:00[SYSTEM]'],
['YYYY-MM-DDThh:mm:ss.f+HH:mm', '2016-03-18T12:38:23.561+01:00'],
['YYYY-MM-DDThh:mm:ss.f-HH:mm', '2016-03-18T12:38:23.56-04:30'],
['YYYY-MM-DDThh:mm:ss.f+HHmm', '2016-03-18T12:38:23.561+0100'],
['YYYY-MM-DDThh:mm:ss.f-HHmm', '2016-03-18T12:38:23.561-0430'],
['YYYY-MM-DDThh:mm:ssZ', '2022-12-24T18:30:35Z'],
['YYYY-MM-DDThh:mm:ss+HH:mm[timezone]', '2017-02-04T17:01:15.846+01:00[Europe/Paris]'],
['YYYY-MM-DDThh:mm:ss+HH:mm[timezone]', '2016-03-18T06:38:23.561-05:00[UTC-05:00]']
Expand All @@ -82,6 +78,19 @@ describe('time.js', () => {
});
});

describe('parses ISO DateTime with zone offset and without time zone and defaults to SYSTEM timezone', () => {
it.each([
['YYYY-MM-DDThh:mm:ss.f+HH:mm', '2016-03-18T12:38:23.561+01:00'],
['YYYY-MM-DDThh:mm:ss.f-HH:mm', '2016-03-18T12:38:23.56-04:30'],
['YYYY-MM-DDThh:mm:ss.f+HHmm', '2016-03-18T12:38:23.561+0100'],
['YYYY-MM-DDThh:mm:ss.f-HHmm', '2016-03-18T12:38:23.561-0430']
])('accepts correct pattern %s', (pattern, isoStr) => {
const zdt = parseISO8601(isoStr);
expect(zdt).toBeInstanceOf(ZonedDateTime);
expect(zdt.zone()).toBe(ZoneId.SYSTEM);
});
});

describe('rejects wrong ISO pattern', () => {
it.each([
['hh:mm:ss,f', '18:00:00,4654'],
Expand Down
12 changes: 7 additions & 5 deletions time.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,15 @@ function _parseISO8601 (isoStr) {
LOCAL_DATE: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])$/, // YYYY-MM-DD
LOCAL_TIME: /^\d{2}:\d{2}(:\d{2})?(\.\d+)?$/, // hh:mm or hh:mm:ss or hh:mm:ss.f
LOCAL_DATE_TIME: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T\d{2}:\d{2}(:\d{2})?(\.\d+)?$/, // LOCAL_DATE and LOCAL_TIME connected with "T"
ISO_8160_FULL: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9])(:[0-5][0-9])?(\.\d+)?(Z|[+-]\d{2}(:\d{2})?)/
ISO_8601_FULL: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9])(:[0-5][0-9])?(\.\d+)?(Z|[+-]\d{2}(:\d{2})?\[.*\])/, // with Zone ID
ISO_8601_OFFSET: /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9])(:[0-5][0-9])?(\.\d+)?(Z|[+-]\d{2}(:\d{2})$)/ // offset only
};
switch (true) {
case REGEX.LOCAL_DATE.test(isoStr): return time.ZonedDateTime.of(time.LocalDate.parse(isoStr), time.LocalTime.MIDNIGHT, time.ZoneId.SYSTEM);
case REGEX.LOCAL_TIME.test(isoStr): return time.ZonedDateTime.of(time.LocalDate.now(), time.LocalTime.parse(isoStr), time.ZoneId.SYSTEM);
case REGEX.LOCAL_DATE_TIME.test(isoStr): return time.ZonedDateTime.of(time.LocalDateTime.parse(isoStr), time.ZoneId.SYSTEM);
case REGEX.ISO_8160_FULL.test(isoStr): return time.ZonedDateTime.parse(isoStr);
case REGEX.ISO_8601_FULL.test(isoStr): return time.ZonedDateTime.parse(isoStr);
case REGEX.ISO_8601_OFFSET.test(isoStr): return time.ZonedDateTime.parse(isoStr).withZoneSameLocal(time.ZoneId.SYSTEM);
}
return null;
}
Expand Down Expand Up @@ -165,7 +167,7 @@ function _convertItem (item) {
} else if (item.rawState instanceof StringType) { // String type Items
return _parseString(item.state);
} else if (item.rawState instanceof DateTimeType) { // DateTime Items
return utils.javaZDTToJsZDT(item.rawState.getZonedDateTime());
return utils.javaZDTToJsZDTWithDefaultZoneSystem(item.rawState.getZonedDateTime());
} else if (item.rawState instanceof QuantityType) { // Number:Time type Items
return _addQuantityType(item.rawState);
} else {
Expand Down Expand Up @@ -230,12 +232,12 @@ function toZDT (when) {

// Java ZDT
if (when instanceof javaZDT) {
return utils.javaZDTToJsZDT(when);
return utils.javaZDTToJsZDTWithDefaultZoneSystem(when);
}

// DateTimeType, extract the javaZDT and convert to time.ZDT
if (when instanceof DateTimeType) {
return utils.javaZDTToJsZDT(when.getZonedDateTime());
return utils.javaZDTToJsZDTWithDefaultZoneSystem(when.getZonedDateTime());
}

// Quantity
Expand Down
2 changes: 1 addition & 1 deletion types/time.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion types/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,21 @@ export function isJsInstanceOfJava(instance: any, type: JavaClass): boolean;
*/
export function javaInstantToJsInstant(instant: JavaInstant): time.Instant;
/**
* Convert Java ZonedDateTime to JS-Joda.
* Convert Java ZonedDateTime to JS-Joda ZonedDateTime.
*
* @memberOf utils
* @param {JavaZonedDateTime} zdt {@link https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/ZonedDateTime.html java.time.ZonedDateTime}
* @returns {time.ZonedDateTime} {@link https://js-joda.github.io/js-joda/class/packages/core/src/ZonedDateTime.js~ZonedDateTime.html JS-Joda ZonedDateTime}
*/
export function javaZDTToJsZDT(zdt: JavaZonedDateTime): time.ZonedDateTime;
/**
* Convert Java ZonedDateTime to JS-Joda ZonedDateTime and default to SYSTEM timezone if not explicitly set.
*
* @memberOf utils
* @param {JavaZonedDateTime} zdt {@link https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/ZonedDateTime.html java.time.ZonedDateTime}
* @returns {time.ZonedDateTime} {@link https://js-joda.github.io/js-joda/class/packages/core/src/ZonedDateTime.js~ZonedDateTime.html JS-Joda ZonedDateTime}
*/
export function javaZDTToJsZDTWithDefaultZoneSystem(zdt: JavaZonedDateTime): time.ZonedDateTime;
/**
* openHAB JavaScript library version
*
Expand Down
2 changes: 1 addition & 1 deletion types/utils.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function javaInstantToJsInstant (instant) {
}

/**
* Convert Java ZonedDateTime to JS-Joda.
* Convert Java ZonedDateTime to JS-Joda ZonedDateTime.
*
* @memberOf utils
* @param {JavaZonedDateTime} zdt {@link https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/ZonedDateTime.html java.time.ZonedDateTime}
Expand All @@ -240,6 +240,21 @@ function javaZDTToJsZDT (zdt) {
return time.ZonedDateTime.ofInstant(instant, zone);
}

/**
* Convert Java ZonedDateTime to JS-Joda ZonedDateTime and default to SYSTEM timezone if not explicitly set.
*
* @memberOf utils
* @param {JavaZonedDateTime} zdt {@link https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/ZonedDateTime.html java.time.ZonedDateTime}
* @returns {time.ZonedDateTime} {@link https://js-joda.github.io/js-joda/class/packages/core/src/ZonedDateTime.js~ZonedDateTime.html JS-Joda ZonedDateTime}
*/
function javaZDTToJsZDTWithDefaultZoneSystem (zdt) {
const jsZDT = javaZDTToJsZDT(zdt);
if (/^[+-]*/.test(jsZDT.zone().toString())) {
return jsZDT.withZoneSameLocal(time.ZoneId.SYSTEM);
}
return jsZDT;
}

module.exports = {
jsSetToJavaSet,
jsArrayToJavaSet,
Expand All @@ -254,5 +269,6 @@ module.exports = {
isJsInstanceOfJava,
javaInstantToJsInstant,
javaZDTToJsZDT,
javaZDTToJsZDTWithDefaultZoneSystem,
OPENHAB_JS_VERSION: VERSION
};
Loading