So I tried recreating what you are seeing. Using the type() function to check if something funky is going on with data types in the background I found out the underlying data always stays a java.util.date.
My guess is that how ignition handles displaying a java.util.date object in different components is inconsistent. You have a few ways of making sure you are displaying date time objects like you want, for example in the expression language dateFormat() and in the scripting library system.date.format.
On a side note, casting a java.util.date to a string using str() yields a decent result such as "Wed Dec 20 07:23:51 CET 2023"
You get the timezone that applies at the point where the java.util.Date, which is itself purely UTC, is converted to a string. If in the gateway process, it will be the gateway's time zone. If in the designer (like the tag browser), it will be the designer's time zone. If in the perspective client using a native component's date formatting, it will be the session time zone. Perspective scripts and expressions run in the gateway. If you want those to use the session timezone, you have to apply it yourself, with Java.
Conclusion: system.date.now() will assign UTC String
system.date.format() will do two things, UTC Time with gatewayOffset
Table component - will render UTC string to integer with "project time" offset
To get Client's time: I need to:
#client time
timeNow = system.date.now()
deviceUtcOffset = self.session.props.device.timezone.utcOffset
gatewayUtcOffset = self.session.props.gateway.timezone.utcOffset
offset = deviceUtcOffset - gatewayUtcOffset
#client time in UTC string with client offset
clientTime = system.date.addHours(timeNow, offset)
#apply date format (apply gateway offset and format it)
clientTimeFormated = system.date.format(clientTime, "yyyy-MM-dd hh:mm:ss a")
return clientTimeFormated
No, it does not. It returns a java.util.Date object. Not a string. Printing or logging it turns it into a string, for that purpose, at that point in your code.
Don't do this. Don't use date arithmetic to "fix" timezoneless date objects. Use zoned date formatting, as shown in the linked topic.
Don't use system.date.format() when trying to use a non-default time zone (non-default for the context the code runs in). Use zoned date formatting, as shown in the linked topic.
Don't print date/time objects, in general, unless you know the context they are in.