system.date.getTimezoneOffset

Hi,

When I code the example form the documentation for system.date.getTimezoneOffset in the script console I get -5.0, which is correct.

However, if I do the same thing in a function defined in the project Library called by a Gateway Event, the returned value seems to always be 0, no matter what I put in for the argument.

    timeNow = system.date.now()
	logger.info("This is the 30 second timer - " + str(system.date.format(timeNow,"yyyy-mm-dd HH:mm:ss z")))
	timeZoneOffset = system.date.getTimezoneOffset(system.date.getDate(2021, 1, 22))
	logger.info("timeZoneoffset = " + str(timeZoneOffset))

I must be missing something that makes the two contexts different?

Thanks
Ken

Date objects are constructed with the system’s local timezone, as determined by the JVM on startup. What’s the system clock on your gateway set to? If it’s accurate to your timezone, then check in your ignition.conf file - you can also force Java to use a specific timezone via a startup parameter.

System clock is correct. There isn’t anything about timezone in ignition.conf. BTW This is on a raspberry Pi. I don’t know enough about Java to do anything with it without breaking something horribly I’m sure.

I don’t understand why it would be correct in the script console, but incorrect in perspective.

Thanks

The user running the gateway might have a different TZ set. What do the system tags say for the gateway’s timezone? [System]Gateway/Timezone?

Etc/UTC. Running datectl:

pi@raspberrypi:~/Ignition-linux-armhf-8.0.14 $ timedatectl 
               Local time: Wed 2021-06-16 13:43:59 EDT
           Universal time: Wed 2021-06-16 17:43:59 UTC
                 RTC time: n/a
                Time zone: America/Indiana/Indianapolis (EDT, -0400)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

I don’t see anything referencing timezone in ignition.conf, these are my java additionals:

Java Additional Parameters

wrapper.java.additional.1=-Ddata.dir=data
#wrapper.java.additional.2=-Xdebug
#wrapper.java.additional.3=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:8000
wrapper.java.additional.4=-Dedition=maker

I did some more investigating tonight. Now even more confused. Here’s some info:

  • Gateway is set to Etc/UTC. There are no timezone overrides in ignition.conf. I will try overriding sometime, but not tonight.

  • Even though the gateway is Etc/UTC, the [System]Gateway/CurrentDateTimetag is displaying local time - EDT or UTC - 4. But the gateway status page is display UTC.

  • When I display the above-mentioned [System]Gateway/CurrentDateTime in a label in perspective, it displays in UTC.

  • I have set Perspective to various timezones - use client, use gateway, manually America/Indiana/Indianapolis. Any way it is set, the timezone displayed on a system.date.now() is UTC. And the system.date.getTimezoneOffset() is 0.0

  • I am writing to the logger in a Project Library script. All times there are UTC

  • If I write system.date.now() to the logger with a Perspective button it writes UTC

So I am at a loss as to how everything is using UTC, EXCEPT the currentDateTime system tag, even though Perspective is set to use America/Indiana/Indianapolis.

Thanks

You are looking at it in the designer, which will use the designer's time zone. Date/time objects in Ignition are instances of java.util.Date which always carry their content as milliseconds UTC, rendering to string in whatever local timezone the code is running. The designer is a local application to your workstation, so it renders in your designer workstation's time zone. Gateway scripts (and Perspective scripts) are using the gateway's time zone for conversions to and from other formats.

You are seeing entirely expected behavior.

Note that Perspective components that are given utc milliseconds and told to render as date can display in the browser's time zone. See this topic:

1 Like

Thanks Phil, that was very helpful, that actually makes sense to me :crazy_face: it hadn’t sunk in that Perspective scripts run on the gateway, it gets pretty complicated of scopes versus where things run.

I am struggling to understand what the purpose of being able to set the timezone in Perspective is if it will always follow the gateway? I did just notice that I could use session.props.timeZoneId to get the ID of the timezone the browser is in, but I don’t see how to get the offset. If I could do that I would be in the recommended keeping time in UTC everywhere except for when displaying paradigm.

Here is why I’m asking - I want an event to happen once a day just after midnight. I have a Gateway event timed script that is running every minute, so I want to detect that I just passed midnight (Eastern). I was planning on offsetting the time with system.date.getTimezonOffset(), but since everything is in UTC that is coming back with 0.0. So I can’t use the Perspective session property to offset to local since this is completely in gateway scope.

I guess I can either change the gateway time in ignition.conf (I don’t know why it isn’t picking up local time when it starts, another small mystery), or there is probably a function I am missing that can change UTC time into Eastern without hardcoding a -4 or -5.

Thanks for the clarifications

Start here:

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/TimeZone.html

Use TimeZone to get a reference to the “America/New York” time zone and get the offset from that.

Perspective scripts will always follow the gateway by default, but if you let Perspective's components do the conversions, the setting matters. As shown in the other topic, just let utc milliseconds (as java.util.Date) go to the browser. Let your Perspective components do the time zone work on the front end.

What do you mean by if a perspective component does a conversion? I tried usinng expressions instead of scripts to return bindings for labels, and still got UTC

As an example, if I want a clock on my perspective screen to show the user what time it is, and it is used in various timezones, how would I do that?

Expressions and transforms and scripts all run in the gateway. I mean a component’s own ability to format data. If there’s no format property for dates, the component can’t do it. For those cases, you would use the browser timezone from the session properties along with java.util.TimeZone to render to string yourself.

@pturmel pretty much nailed it.

Overall, we are currently working towards normalizing the inconsistencies regarding timezones in Perspective.

Applicable components will begin to respect the session props timezoneId, so if that changes, the timezone used to format incoming date objects or timestamps will also change.

As far as scripts, expressions, and transforms go, that’s tbd.

ok, thanks Phil. here are a couple more things I have discovered.

My gateway is probably set to UTC because I am using the @Kevin.Collins 8.1.5 ignition docker image, which is probably set to UTC. I will go and change ignition.conf to address that.

As far as a real-time clock on the display, my integrator (Eric from Flexware) pointed out that there is a UTC offset property under device. So I implemented a clock display with:

gatewayTimezoneOffset = system.date.getTimezoneOffset()
deviceTimeZoneOffset = self.session.props.device.timezone.utcOffset
# subtract gatewaytimezoneoffset from devices offset to get offset for display 
tzToday = system.date.addHours(value, int(deviceTimeZoneOffset - gatewayTimezoneOffset))
formatted = system.date.format(tzToday,hh:mm:ss a)
return formatted

Thanks for everyone’s’ help, this has been a learning experience!

@ken.maze, you can set the Gateway time zone by setting environment variable TZ=America/Chicago (or whatever you need based on the timezone database entries… You will then see that timezone reflect on the gateway status page (as well as when shelling into the container).

Nice, that worked like a charm Kevin. And my time display stayed in the same timezone as my browser. Yay!