Yiwei Yu

Posted on: 2026-01-09

How to Properly Handle Time Zones in Web Applications

Any web page that displays time needs to deal with time zones, because users can be located anywhere in the world.  You don’t want user at 10:00 a.m. seeing content that looks like it was published 5:00 at p.m. Handling time zones is not optional — it is a fundamental requirement for any serious web project.

The core principle is simple: always store time in UTC in your database.

On the frontend, you should first obtain the user’s time zone and send it to the backend. 

// 发送时区数据到后端
$.ajax({
    url: '/getUserTimeZone', // 后端的接口地址
    type: 'POST',           // 请求方法
    contentType: 'application/json', // 指定请求的数据类型
    data: JSON.stringify({  // 将数据转换为 JSON 格式
        timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone // 发送的时区数据
    }),
    success: function (response) {
        console.log('时区数据发送成功:', response); // 成功后返回的数据
    },
    error: function (xhr, status, error) {
        console.error('时区数据发送失败:', error); // 失败时的错误信息
    }
});
JavaScript

The backend can then store this information in the session. Since sessions may expire when users log in or log out, special care must be taken to preserve the time zone information so it does not disappear along with the session.

@PostMapping("/getUserTimeZone")
public ResponseEntity<String> getUserTimeZone(@RequestBody Map<String, String> data, HttpSession session) {
    String userTimeZone = data.get("timeZone");
    session.setAttribute("userTimeZone", userTimeZone);

    // 返回响应
    return ResponseEntity.ok("时区 " + userTimeZone + " 接收成功!");
}
Java

When a user publishes content that contains time information, their local time should be converted into UTC before being saved to the database. Then, when displaying time data, you get the UTC times from the database and convert it into the user’s local time zone based on the time zone stored in the session. With this approach, users in any region will always see times that match their own local time.

Save UTC timestamp:

// 将时间转换为用户的时区
ZoneId userZoneId = ZoneId.of(userTimeZone != null ? userTimeZone : "UTC");
articles.forEach(article -> {
    if (article.getCreateTime() != null)
        article.setCreateTime(article.getCreateTime().withZoneSameInstant(userZoneId));
    if (article.getUpdateTime() != null)
        article.setUpdateTime(article.getUpdateTime().withZoneSameInstant(userZoneId));
});
Java

Convert it into the user’s local time zone:

ZoneId zone = ZoneId.of(userTimeZone != null ? userTimeZone : "UTC");
blogs.forEach(b -> b.setCreateTime(b.getCreateTime().withZoneSameInstant(zone)));
Java

Display on HTML:

<div class="description middle-font">
    <p th:text="${#temporals.format(blog.createTime, 'yyyy-MM-dd')}">2019-08-20</p>
</div>
HTML

One important note is that during the process of converting UTC timestamps into the user’s local time zone, you should never directly set the converted value back into your persistent entities. Doing so can easily lead to dirty data and unintended database updates.

In my own project, I use DTOs instead of entities wherever time needs to be displayed. The converted local time is injected directly into the DTO. This approach avoids data pollution, keeps the domain model clean, and also improves overall performance.




Comments (
)
Sign in to comment
0/500
Comment