How to use DateTimeFormatter.ofPattern in ECMA 2021 openhab rules

Hi,

I’m rewriting all my former DSL rules to javascript ECMA 2021 (openhab 3.4.5)
Now I noticed when I want to use the the following, I’m getting an error.

....next_Holiday_Date.format(time.DateTimeFormatter.ofPattern("E dd.MM.yyyy")).toString);

I read at Manual | js-joda that I can import the localized version. But how can I do this into OpenHab 3.4.5 ui rule engine using application/javascript;version=ECMAScript-2021? With the import directive it doesn’t work.

I already installed with npm i @js-joda/locale_de the german localized version of the library.

@js-joda/locale_de

My ECMA 2021 try doesn’t work:

//import { DateTimeFormatter, ZonedDateTime } from '@js-joda/locale_de';
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);

function sleep(msec) 
{
  var e = new Date().getTime() + (msec);
  while (new Date().getTime() <= e) {}
}

var heute = time.ZonedDateTime.now().plusDays(0);
var morgen = time.ZonedDateTime.now().plusDays(1);
var currentHoliday  =  actions.Ephemeris.getBankHolidayName(heute, "/etc/openhab/services/Holidays_de.xml");
var nextHoliday  =  actions.Ephemeris.getNextBankHoliday(morgen, "/etc/openhab/services/Holidays_de.xml");
var untilHoliday    = actions.Ephemeris.getDaysUntil(nextHoliday, "/etc/openhab/services/Holidays_de.xml");
var next_Holiday_Name = actions.Ephemeris.getHolidayDescription(nextHoliday);
var untilWeekend = new Boolean(actions.Ephemeris.isInDayset("beforeWeekend"));
var next_Holiday_Date = time.ZonedDateTime.now().plusDays(untilHoliday);
var current_Holiday_Name = actions.Ephemeris.getHolidayDescription(currentHoliday);
console.log(next_Holiday_Name);
items.getItem("NextFeiertagName").postUpdate(next_Holiday_Name);
logger.info("Nächster Feiertag ist {} in {} Tagen", next_Holiday_Name, untilHoliday);
logger.info("Date: {}", (next_Holiday_Date).toString());
logger.info("Nächster Feiertag {}, {}", next_Holiday_Name, next_Holiday_Date.format(time.DateTimeFormatter.ofPattern("E dd.MM.yyyy")).toString);

Please don’t post screen shots where possible. They are almost impossible to read. Screen shots of code and logs are particularly unusable.

As far as the localization, I don’t know the solution. I know a couple of years ago we looked into making all the localization stuff a part of the library but it exploded the size of the library beyond acceptable limits.

There is a number of things I see that are problematic here too which might be relevant.

Use require, not Import. Also note that Joda-JS is already included for you under time so you don’t need to import anything anyway.

  • Why not a timer?
  • You don’t appear to be using this anyway so why is it here?
  • Where possible, use the joda-js DateTime Classes (e.g. time.ZonedDateTime) instead of the native JavaScript Date class.
  • The following will do the same thing using what’s built into openhab-js
function sleep(msec) {
  const e = time.toZDT(msec);
  while(time.toZDT().isBefore(e)) { }
}

This is a noop. It’s a relatively complicated line that doesn’t do anything.

var heute = time.toZDT();

When not passed anything, toZDT returns now.

time.toZDT('P1D'); cam work here. toZDT accepts ISO8601 duration strings and will automatically add them to now. As you saw above, if you pass it a number, it will add that as msec to now.

As far as I can tell, the purpose of the formatting is just for a log statement. You can see the discussion on handling local formatting at [WIP] Time: Add access to JS-Joda Locales by florian-h05 · Pull Request #94 · openhab/openhab-js · GitHub but ultimately it ended up being a no-fix. I don’t think there is a work around for this using JS. You might be able to work around this by using the Java time classes but you have to decide how much effort it is worth to format a log statement.

My Ephemeris rule converted to EMCA 2021 works now, thanks @rlkoshak for some useful hints!

var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
var OPENHAB_CONF = java.lang.System.getenv("OPENHAB_CONF");
const { Locale } = require(OPENHAB_CONF + '/automation/js/node_modules/' +'@js-joda/locale_de');

var heute = time.toZDT();
var morgen = time.toZDT('P1D');
var currentHoliday  =  actions.Ephemeris.getBankHolidayName(heute, "/etc/openhab/services/Holidays_de.xml");
var nextHoliday  =  actions.Ephemeris.getNextBankHoliday(morgen, "/etc/openhab/services/Holidays_de.xml");
var untilHoliday    = actions.Ephemeris.getDaysUntil(nextHoliday, "/etc/openhab/services/Holidays_de.xml");
var next_Holiday_Name = actions.Ephemeris.getHolidayDescription(nextHoliday);
var untilWeekend = new Boolean(actions.Ephemeris.isInDayset("beforeWeekend"));
var next_Holiday_Date = time.ZonedDateTime.now().plusDays(untilHoliday);
var current_Holiday_Name = actions.Ephemeris.getHolidayDescription(currentHoliday);

// Converts ZoneDateTime to readable Date String. (uses @js-joda/locale_de [npm install @js-joda/locale_de])
var mydate = next_Holiday_Date.format(time.DateTimeFormatter.ofPattern('E dd MMM yyyy').withLocale(Locale.GERMANY));
logger.info('de formatted string: {}', mydate);
logger.info(next_Holiday_Name + " am " + mydate);// toDateString('en-US'));
items.getItem("TageBisFeiertag").postUpdate(next_Holiday_Name + ", " + mydate);
if (actions.Ephemeris.isBankHoliday()) {
   console.log("EphemerisRule_0 Heute ist ein Feiertag");
   items.getItem('Feiertag').sendCommand('ON'); // Schalter Feiertag setzen
   //items.getItem('Urlaub').sendCommand('ON') // Schalter Urlaub setzen
   items.getItem('FeiertagName').postUpdate(current_Holiday_Name); 
}
if (actions.Ephemeris.isWeekend()) {
   console.log("EphemerisRule_0 ist Wochenende"); 
   items.getItem('Wochenende').sendCommand('ON'); 
   items.getItem('Lange_schlafen').sendCommand('ON'); 
}
if (!(actions.Ephemeris.isWeekend())) { 
  console.log("EphemerisRule_0 ist Arbeitswoche");
   //items.getItem('Urlaub').sendCommand('OFF') // Schalter Urlaub setzen
  items.getItem('Wochenende').sendCommand('OFF');
  items.getItem('Lange_schlafen').sendCommand('OFF'); 
}
if (!(actions.Ephemeris.isBankHoliday())) {
  console.log("EphemerisRule_0 Heute ist kein Feiertag");
  items.getItem('Feiertag').sendCommand('OFF'); 
   //items.getItem('Urlaub').sendCommand('OFF') // Schalter Urlaub setzen
  if(items['Wochenende'].state == 'ON') {
    items.getItem('Lange_schlafen').sendCommand('ON');
   } else{
     items.getItem('Lange_schlafen').sendCommand('OFF');
     }
   items.getItem('FeiertagName').postUpdate('-');
  }
if (untilHoliday == 1) {
  console.log("EphemerisRule_0 Nur noch ein Tag bis Feiertag");
  items.getItem('Lange_schlafen').sendCommand('ON'); // Lange schlafen ein
}
if (untilWeekend == true) {
  console.log("EphemerisRule_0 Nur noch ein Tag bis Wochenende");
  items.getItem('Lange_schlafen').sendCommand('ON'); // Lange schlafen ein
}

example output in log:

2023-08-07 15:01:10.238 [INFO ] [org.openhab.rule.Ephemeris_0        ] - de formatted string: Di. 15 Aug. 2023
2023-08-07 15:01:10.240 [INFO ] [org.openhab.rule.Ephemeris_0        ] - Mariä Himmelfahrt am Di. 15 Aug. 2023
2023-08-07 15:01:10.287 [INFO ] [hab.automation.script.ui.Ephemeris_0] - Ephemeris_0 ist Arbeitswoche
2023-08-07 15:01:10.296 [INFO ] [hab.automation.script.ui.Ephemeris_0] - Ephemeris_0 Heute ist kein Feiertag
1 Like