Timezones – the ultimate “fun” problem every developer loves to hate. If you think daylight saving time is annoying, try handling time across multiple continents, especially in a business where things need to be perfectly synchronized.
The Problem: What Time is it Really? Link to heading
Imagine this: you’re managing a project from Switzerland, but your cleaning teams are operating in Japan. Someone reports an issue at 2 PM local time, but when you check your system, it says 3 AM. Huh? Did they really call in the middle of the night? No, your system just decided to be overly helpful and converted everything into your local timezone. Great for Google Calendar, terrible for tracking real-time issues.
The Technical Magic Link to heading
To avoid chaos, we need a system that ensures a cleaning area closing at 08:00 AM in Japan actually shows up as 08:00 AM in Japan – even if you’re looking at it from Switzerland. How? By always working with UTC behind the scenes and displaying local time where needed.
Here’s the flow:
- The browser records the date and time.
.toISOString()transforms it into UTC.- The backend receives and processes it as UTC.
- When reading, it gets converted back to the correct local timezone.
Simple, right? (Well, not really, but that’s why we have code.)
Date Handling (Example 25.10.2021 10:00:00) Link to heading
Backend Shenanigans Link to heading
- ZonedDateTime.now() is always UTC. No exceptions. Ever.
- If you need to convert, use
TimeZoneHelper. Otherwise, you’ll cry later. - Before saving anything in the database, make sure it’s UTC.
- Need the correct weekday? Don’t just use
.getDayOfWeek(), because that’ll give you the UTC weekday, not the local one. Instead, useTimeZoneHelper.getDayOfWeekInTheZone().
Frontend – Where Things Get Even Trickier Link to heading
Frontend needs to play along, too. Since JavaScript loves to mix local and UTC time, we force it to always use the economic entity’s timezone. That means:
- Set the default timezone correctly in the state (
moment.tz.setDefault(value.data.timeZone)). - Use
DateTimeConverterfor views. - If you compare dates, use moment.js – but be careful! Too many conversions kill performance.
Performance Benchmark: Link to heading
| Conversion | Time |
|---|---|
| new Date() | 2-4 ms |
| moment() | 40-70 ms |
In other words: use moment.js sparingly.
Time Handling: (Example 17:00:00) Link to heading
Saving just the time (without a date) in UTC? Forget it. Daylight saving time will ruin everything.
Example (we wanne save the time 17:00:00):
- Database stores
15:00:00for ETC summer (+2). - In summer (+2), UTC is
17:00→ Correct ✅ - In winter (+1), UTC is
16:00→ Wrong ❌
The Fix Link to heading
We always store local time in the database and apply timezone conversion only when needed.
- Database stores
17:00:00in ETC. - In summer (+2), UTC is
15:00→ Correct ✅ - In winter (+1), UTC is
16:00→ Correct ✅
Setting Time on Dates Link to heading
If you need to set a specific time on a date object, be careful. First, get the local midnight time, then apply the hours and minutes to avoid accidentally shifting the date. Use the helper:
TimeZoneHelper.setLocalTimeOnZonedDate(ZonedDateTime date, DateTimeZone zone, LocalTime time)
This ensures that when you set 17:00:00, it actually stays 17:00:00 and doesn’t turn into 16:00:00 or 18:00:00 due to time zone shifts.
Comparing Link to heading
- Strip the date and only compare time (
now.isAfter(compareTime)). - If comparing a date, first convert it to the correct zone, then add local time.
Comparing Times Across Timezones Link to heading
Comparing times can be tricky because you need to be in the correct zone first. Here’s a better way:
LocalTime now = TimeZoneHelper.setToZone(now, economicEntity.getDateTimeZone()).toLocalTime();
now.isAfter(compareTime);
If you need to compare a specific day’s time, always change it to the right timezone first before adding the local time. Otherwise, you might end up comparing apples to UTC oranges.
Frontend Simplicity Link to heading
In the frontend, we keep time handling as simple as possible. No conversion, just treat it as a string and send it to the backend. Let the backend do the heavy lifting, because frontend date handling is already complicated enough.
Conclusion Link to heading
Timezones are evil, but with the right approach, we can at least keep them under control. The golden rule? Store UTC, display local time, and always double-check conversions – unless you enjoy debugging at 3 AM.