Time conversion in ECMAScript 11

I could not figure out, how I can use an ISO8601 period of time for comparison, i.e. if an item update happened longer ago that xyzy seconds.

Here is what I tried so far:

  name: "Teakettle",
  description: "Turn teakettle mains supply off as soon as thermostate switched off when water is boiling",
  triggers: [
    triggers.ItemStateChangeTrigger("SchukoTeaKettleSW_State", "OFF", "ON"),
  execute: (event) => {
     // returns timestamp of the last persistet value, not the last change
     // 2023-10-15T20:27:00.210+02:00[Europe/Berlin]

    //console.log("Object with Last Change Time", items.SchukoTeaKettleSW_Energy_Counter.history.previousState(true));
    // Returns the complete object, however, the timestamp shows the last change of the item
    /* {
      "rawState": {},
      "state": "0.1213 kWh",
      "numericState": 0.1213,
      "quantityState": {
        "raw": {}
      "timestamp": "2023-10-15T10:57:00.160+02:00[Europe/Berlin]"
    var lastChangeTime = items.SchukoTeaKettleSW_Energy_Counter.history.previousState(true).timestamp;
//    console.log("Last Change Timestamp", lastChangeTime);
    var currentTime = time.ZonedDateTime.now(); // local SYSTEM time
//    console.log("local DateTime", currentTime);

    var iso8601Time = time.Duration.between(lastChangeTime, currentTime);
//    console.log("Duration ", iso8601Time);
    // produces "Duration  PT338H12M57.806S" Period of Time 338 hours, 12 Minutes ...

    var uxTimestamp = new Date(iso8601Time).getTime() / 1000;
    // console.log("UX Timestamp ", uxTimestamp);

  tags: ["Power", "Safety"],
  id: "TeakettleOff"

What I could write to the log was:

Last Change Timestamp 2023-10-15T10:57:00.160+02:00[Europe/Berlin]
local DateTime 2023-11-02T15:53:15.992+01:00[SYSTEM]
Duration PT437H56M15.832S
UX Timestamp NaN

Yet I am not used to work with ISO8601 periods of time. My question is, how could I determine if the duration between two events is e.g. longer than 15 seconds? Conversion to unix timestamp in milliseconds?

P.S. the log outputs are not exactly accurate because I recorded them over time while tinkering with the code but they should help to see the formats.

Please review the docs for joda-js and the docs for time. There is a lot built in so that you never have to mess with any of this, or when you do to make it much easier.

var lastChangeTime = items.SchukoTeaKettleSW_Energy_Counter.history.previosState(true).timestamp; // This is already a ZonedDateTime, leave it alone
var currentTime = time.toZDT(); // Passing nothing to this returns `now`
var delta = time.Duration.between(lastChangeTime, currentTime); // generate a Duration
if(delta.compareTo(time.Duration.ofSeconds(15)) > 0){ // Compare the duration to a duration of 15 seconds

It is almost never the best solution to convert to epoch. Keep everything as a ZonedDateTime or sometimes it makes sense to work with a LocalDateTime (to convert a ZonedDateTime to a LocalDateTime it’s a simple myZDT.toLocalDateTime()).

When you don’t have a ZonedDateTime, if it makes any sort of sense at all, time.toZDT() will convert what you have to a ZonedDateTime. See the chart in the docs for details.

Note that a Duration isn’t an ISO8601 Time, it’s a duration, an amount of time. It’s toString() outputs an ISO8601 formatted duration String, and it can parse such a String to create a new duration (e.g. "PT15S" is 15 seconds). But the Duration is an Object with all sorts of methods to work with it and manipulate it. Looking at the reference for Duration you’ll find all sorts of ways to manipulate a Duration. For example, this would work too:

if(delta.seconds() > 15) {

Excellent - thanks for the quick reply and the thorough explanation!

Log file output is now:

Last Change Timestamp 2023-10-15T10:57:00.160+02:00[Europe/Berlin]
local DateTime 2023-11-02T18:56:12.048+01:00[SYSTEM]
Duration PT440H59M11.888S
greater than 15 sec

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.