Dates and time zones
Read this when a time or date in an expression comes out one or two hours wrong, or one day off. It applies to Deem Java Expression and Deem Script Expression.
How a date reaches the expression
Section titled “How a date reaches the expression”Date and Timestamp fields reach the expression as a QueryDate. An empty field is an empty
QueryDate, never null: test it with field.isEmpty().
A QueryDate is a point in time plus a time zone. Reading the hour, day, week or a formatted
text uses that zone. Which zone a value carries depends on where it came from:
| Source | Time zone |
|---|---|
| Date or Timestamp field | UTC |
Text with an offset (2026-10-19T14:21:22+02:00) | UTC |
Text without an offset, YMD8 number (20261019) | server time zone |
ZDateTime, anything from ZTools | server time zone |
So in Norway a Date field read straight away shows UTC time: one hour behind in winter, two in summer. Near midnight the date and the week can also be wrong.
Read in the right time zone
Section titled “Read in the right time zone”Convert before you read. The conversion keeps the point in time and only changes the zone.
field.zoneCet().toHHMM() // Europe/Oslofield.zoneCet().getYMD8()field.zone("Europe/Stockholm").getHour()field.zoneUtc().getYMD8() // explicit UTC- Use a named zone (
Europe/Oslo), never a fixed offset (+01:00). A fixed offset is one hour wrong in summer. zoneSystem()uses the server time zone, so it is only right when that zone is set (below).- Writing a
QueryDateback to a Date or Timestamp field keeps the point in time. Only convert when you read parts of the date.
ZTools
Section titled “ZTools”Everything in ZTools uses the server time zone: reading (getHour, toHHMM, toYMD8,
getWeek, …), formatDate(..), and the dates it returns from setDate(..), setTime(..),
asDate(..), addDays(..) and the other add/with functions. M3 numbers (YMD8 date, HHMMSS
time) are read as server time. So ZTools.setDate(orderTime).toHHMM() gives server time, even
though orderTime arrives as UTC. formatDate returns null for an empty date.
So ZTools is only right when the server time zone is set. field.zoneCet() is right
everywhere.
Example: Norway
Section titled “Example: Norway”An order is registered on 16 July 2026 at 00:30 Norwegian time (summer, UTC+2). The Date field
orderTime holds that point in time, which is 15 July 22:30 UTC.
| Expression | Server in UTC | Server in Europe/Oslo |
|---|---|---|
orderTime.toHHMM() | 22:30 ✗ | 22:30 ✗ |
orderTime.getYMD8() | 20260715 ✗ | 20260715 ✗ |
ZTools.toHHMM(orderTime) | 22:30 ✗ | 00:30 ✓ |
ZTools.toYMD8(orderTime) | 20260715 ✗ | 20260716 ✓ |
ZTools.setDate(orderTime).toHHMM() | 22:30 ✗ | 00:30 ✓ |
ZTools.formatDate(orderTime, "HH:mm") | 22:30 ✗ | 00:30 ✓ |
orderTime.zoneSystem().toHHMM() | 22:30 ✗ | 00:30 ✓ |
ZDateTime.toHHMM() (run at the same moment) | 22:30 ✗ | 00:30 ✓ |
orderTime.zoneCet().toHHMM() | 00:30 ✓ | 00:30 ✓ |
orderTime.zoneCet().getYMD8() | 20260716 ✓ | 20260716 ✓ |
- Only
zoneCet(), orzone(..)with a named zone, is right on both servers. - In winter (UTC+1) the error is one hour. Only times between 00:00 and 01:00 move to the day before.
Set the server time zone
Section titled “Set the server time zone”The server time zone is the Java default zone of the Integrator process. It follows the operating system unless it is set, so the same pipeline can give different results on two servers. Set it on every machine that runs pipelines, and keep the memory setting:
SETX /m HOP_OPTIONS "-Xmx2048m -Duser.timezone=Europe/Oslo"export HOP_OPTIONS="-Xmx2048m -Duser.timezone=Europe/Oslo"The new value applies when Integrator is started again. -Duser.country=NO sets the language
and number format, not the time zone. Check it with an expression:
java.util.TimeZone.getDefault().getID().
Checklist
Section titled “Checklist”- Server:
-Duser.timezone=<zone>inHOP_OPTIONS. - Expression: convert with
zoneCet()orzone(..)beforetoHHMM,getHour,getYMD8,getWeekorformat(..). - Empty dates:
field.isEmpty(), notfield == null. - Old expressions that add one or two hours by hand: replace the hours with
zoneCet().