Date and Time


This Library adds support to get, create, compare and modify Times and Dates with Blockly.


Creation of ZonedDateTime with Ephemeris → date block
Please be aware that the existing blocks for dates set their time to 0 and the zone offset to UTC. Although the date block is set as shadow in all blocks of this library, it should not be used. If you compare dates only it does not matter.


Obtains the current date-time from the system clock in the default time-zone.

ZDT with date <year>-<month>-<day> and time <hour>:<minute>:<second>

Creates a ZonedDateTime based on the given input for date and time with nanos set to 0 and the system’s time-zone. Values must be valid.

Allowed values

year: the year
month: 1 to 12
day: 1 to 28-31
hour: 0 to 23
minute: 0 to 59
second: 0 to 59

ZDT from item <item>

Get the ZonedDateTime from item’s state. Error if item is undef/NULL.

set item <item> to ZDT <zdt>

Update state of a DateTime item to the provided ZonedDateTime.

copy of <zdt> with time set to <hour>:<minute>:<second>

Returns a copy of the provided ZonedDateTime with hours, minutes and seconds altered.

Allowed values

hour: 0 to 23
minute: 0 to 59
second: 0 to 59

copy of <zdt> +/- <number> <datetime_unit>

Returns a copy of the provided ZonedDateTime with the specified value added or subtracted.

copy of <zdt> with <datetime_unit> altered to <number>

Returns a copy of the provided ZonedDateTime with the selected field altered.

is <zdt1> before/after/equal <zdt2> use date and time/date/time with resolution of <datetime_unit>

Checks if the instant of the first ZonedDateTime is before/after/equal that of the second ZonedDateTime. You can select if you want to compare all components, date only or time only.

is <zdt1> between <zdt2> and <zdt3> use date and time/date/time

Check if the instant of the first ZonedDateTime is between the two other ZonedDateTime. You can select if you want to compare all components, date only or time only.

get <datetime_unit> from <zdt>

Returns the selected unit as number.

<datetime_unit> between <zdt1> and <zdt2>

Calculates the amount of time between two ZonedDateTime objects. The result will be negative if the second object is before the first one.


Version 0.3

  • Fixed code for comparison

Version 0.2

  • Fixed comparison with time only
  • Fixed wrong tooltip
  • Added block compare_zdt_between_zdt_and_zdt

Version 0.1

  • initial release




Hi David,

I am almost done with porting your blocks to blockly core. You lately added the following block to the library. I know what it does but I wonder what you/we need it for. Can you provide an example?



PS: I did not add your “set item” as it can be achieved by using a generic post-command-block (I do understand that you added it for convenience though in your library). I also combined blocks 4-6 into one block which is much more versatile but couldn’t been done with the block library because it uses mutators. I also added e.g. small additions like milli seconds support. Other than that the new blocks are very much based on your ideas and your work - so this is very much appreciated and I will add that appreciation to the PR that will come eventually.

Hello Stefan,

The idea was to get the local time in other regions of the world. But I didn’t pursue the idea any further and forgot to remove the block in v0.1. I’m not sure if anyone is using this block(don’t think so) and also left it in v0.2 of the library.

Sounds nice.

Thank you work your work to port this library to the core.

1 Like

From now on all these blocks (although a small number of them in a bit modified form) are available in openHABs core blocks. You can find the information about that at New Datetime Blocks, easier Logging and CRLF

Thanks David for the original contribution here.

1 Like

There is an error in the code of the date-between block that is also present in the core blocklies. See the PR that fixes it. You may want to fix it here as well:

Changed as suggested. Thank you for the hint.

After migrating to OH4, a rule I had written a while ago and hadn’t thought about failed. I was able to figure out that it was the “set item” block that caused the failure:

2023-07-30 08:51:49.263 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: ReferenceError: "events" is not defined
        at <js>.:program(<eval>:8) ~[?:?]
        at org.graalvm.polyglot.Context.eval( ~[?:?]
        at ~[?:?]
        at ~[?:?]
        at javax.script.AbstractScriptEngine.eval( ~[java.scripting:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval( ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval( ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval( ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval( ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0( ~[?:?]
        at java.util.Optional.ifPresent( ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute( ~[?:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.executeActions( ~[?:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runNow( ~[?:?]
        at ~[?:?]
        at ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke( ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke( ~[?:?]
        at java.lang.reflect.Method.invoke( ~[?:?]
        at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation( ~[bundleFile:3.4.5]
        at org.apache.cxf.service.invoker.AbstractInvoker.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.jaxrs.JAXRSInvoker.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.jaxrs.JAXRSInvoker.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.interceptor.ServiceInvokerInterceptor$ ~[bundleFile:3.4.5]
        at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage( ~[bundleFile:3.4.5]
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.ServletController.invokeDestination( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.ServletController.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.ServletController.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest( ~[bundleFile:3.4.5]
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost( ~[bundleFile:3.4.5]
        at javax.servlet.http.HttpServlet.service( ~[bundleFile:4.0.4]
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service( ~[bundleFile:3.4.5]
        at org.ops4j.pax.web.service.spi.servlet.OsgiInitializedServlet.service( ~[bundleFile:?]
        at org.eclipse.jetty.servlet.ServletHolder.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter( ~[bundleFile:9.4.50.v20221201]
        at org.ops4j.pax.web.service.spi.servlet.OsgiFilterChain.doFilter( ~[bundleFile:?]
        at org.ops4j.pax.web.service.jetty.internal.PaxWebServletHandler.doHandle( ~[bundleFile:?]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle( ~[bundleFile:9.4.50.v20221201]
        at ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.servlet.ServletHandler.doScope( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.session.SessionHandler.doScope( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle( ~[bundleFile:9.4.50.v20221201]
        at org.ops4j.pax.web.service.jetty.internal.PrioritizedHandlerCollection.handle( ~[bundleFile:?]
        at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.Server.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.HttpChannel.dispatch( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.HttpChannel.handle( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.server.HttpConnection.onFillable( ~[bundleFile:9.4.50.v20221201]
        at$ReadCallback.succeeded( ~[bundleFile:9.4.50.v20221201]
        at ~[bundleFile:9.4.50.v20221201]
        at$ ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce( ~[bundleFile:9.4.50.v20221201]
        at ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob( ~[bundleFile:9.4.50.v20221201]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$ ~[bundleFile:9.4.50.v20221201]
        at ~[?:?]
2023-07-30 08:51:49.334 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'SetFrontSmartLightTuyaStatus' failed: org.graalvm.polyglot.PolyglotException: ReferenceError: "events" is not defined

and the code from the UI

events.sendCommand('FrontEntrySmartLightLastOnlineTimeStamp', new deibich_blockly_DateTimeType(;

for block

Changing to the post update block fixes the problem.

I thought about just removing the custom dateTime Blockly library, but wanted to understand whether blocks I used from the library that have been replaced/supplanted by core blocks of the same name will smoothly transition to their new ones, or if I need to hunt for them and do something. I suppose I can always try and see if anything complains, but since not all rules run frequently, I would prefer a more scientific approach.

Do we still need it in the Add-on Store?
I think 99% is available now in core?