0 votes
22 views
ago by (30.6k points)
A date entered as 2025-06-30 in a coach shows as 2025-06-29 in a later coach, e-mails or the database, depending on where the user sits. What causes the shift and what is the correct handling of dates and time zones across browser, server and database?

1 Answer

0 votes
ago by (30.6k points)

The shift comes from mixing date-only values with timestamps: BAW's Date type is a timestamp (a moment in time, serialised in UTC); the browser turns "2025-06-30" into midnight in the browser's time zone, the server (or a browser in another zone) shows that moment in its zone, and midnight in Sydney is the previous evening in Berlin - hence the day change. Rules:

  1. Decide per field whether it is a date or a moment. Birthdays, due dates and invoice dates are calendar dates; "submitted at" is a moment. Store calendar dates as strings (2025-06-30) or as Date values normalised to 12:00 UTC (the traditional workaround - a day change needs a 12-hour offset which no time zone has); store moments as Date and format them per viewer.
  2. Coaches: the UI Toolkit Date Picker has options for date-only handling (bind it to a String in ISO format, or use its "date only / UTC" style configuration); check the control's documentation of your toolkit version and use the same setting everywhere.
  3. Server scripts: never build dates with new Date(y, m, d) on the server (server zone) for calendar dates; parse and format explicitly with the Java classes and an explicit zone.
  4. Database: DATE columns receive the date part in the JVM's zone when you pass a Date; pass the ISO string (or a java.sql.Date built from the string) for calendar dates, and TIMESTAMP for moments; keep JVM (server) time zone and database session time zone identical and documented - on CP4BA the containers run in UTC.
  5. E-mails and documents: format moments in the recipient's zone explicitly.
// server script helpers
// calendar date string -> Date at 12:00 UTC (safe for storage in a Date variable)
function dateOnly(iso) { var p = iso.split("-"); return new Date(Date.UTC(+p[0], +p[1] - 1, +p[2], 12, 0, 0)); }
// Date -> calendar date string in a given zone
function toIso(d, zone) {
  var f = new Packages.java.text.SimpleDateFormat("yyyy-MM-dd"); f.setTimeZone(Packages.java.util.TimeZone.getTimeZone(zone)); return String(f.format(d));
}
tw.local.invoiceDate = dateOnly(tw.local.invoiceDateText);                 // "2025-06-30"
tw.local.dueText = toIso(tw.local.dueDate, "Europe/Berlin");
// moment for the reader
var f = new Packages.java.text.SimpleDateFormat("dd.MM.yyyy HH:mm z"); f.setTimeZone(Packages.java.util.TimeZone.getTimeZone(tw.local.userZone));
tw.local.submittedText = String(f.format(tw.local.submittedAt));

// coach (client side): show a date-only value without zone shift
var iso = ${{InvoiceDate}}.getData();                        // "2025-06-30" when bound to a String
var parts = iso.split("-"); var local = new Date(+parts[0], +parts[1]-1, +parts[2]);   // midnight local, display only

Checklist for an existing app with the problem: list every Date variable and classify it; switch calendar dates to String (or normalise to noon UTC) in the next snapshot with a migration script for running instances; align JVM and database zones; and add a test user in a far-away time zone to the regression tests.

References

Related questions

723 questions

807 answers

98 comments

4.8k users

Join BPM Community Discord Channel

Welcome to BPM Tips Q&A, Community wiki/forum where you can ask questions and receive answers from other IBM BPM experts and members of the community. Users with 2000 points will automatically be promoted to expert level.
Created by Dosvak LLC
Our Youtube Channel
...