# Docker 容器时区问题：UTC 导致的自然日业务刷新异常



最近将微信小程序后端迁移到 Docker 后，出现了“每日刷新”相关 Bug，例如：

- 每日广告次数未刷新
- 次日仍然沿用前一天状态

排查后发现，问题并不在业务逻辑，而是：

- Docker 容器默认使用 UTC 时区。

而业务中的“每日刷新”逻辑实际上是基于东八区自然日实现的。

例如：

```
if user.last_ad_time != today:
    user.today_ad_views = 0
```

当中国时间已经进入第二天时：

| 中国时间         | UTC 时间         |
| ---------------- | ---------------- |
| 2026-05-19 00:30 | 2026-05-18 16:30 |

后端仍然认为“还是昨天”，从而导致自然日逻辑整体延迟 8 小时。

------

## 最终方案

### 数据库存储统一使用 UTC

数据库中的 datetime / timestamp 统一存 UTC。

优点：

- 避免时区混乱
- 避免夏令时问题
- 多服务容易统一

------

### 前端负责本地化显示

后端返回 UTC：

```json
{
  "created_at": "2026-05-18T16:30:00Z"
}
```

前端按用户本地时区格式化：

```js
new Date(utcTime).toLocaleString()
```

------

### 自然日业务明确业务时区

像：

- 每日限额
- 定时刷新

这类逻辑本质上依赖“业务时区”。

对于面向中国用户的服务，直接统一：

```dockerfile
ENV TZ=Asia/Shanghai
```

通常是最简单稳定的方案。

##### **精简镜像中的 tzdata 问题**

如果使用 Alpine / slim 等精简镜像：

则可能需要额外安装：

```shell
RUN apk add --no-cache tzdata ca-certificates
```

------

## 总结

目前采用的时间处理策略：

| 层级             | 策略               |
| ---------------- | ------------------ |
| 数据库存储       | UTC                |
| 前端显示         | 用户本地时区       |
| 后端 Docker 容器 | `TZ=Asia/Shanghai` |


---

> 作者: [fupcode](https://github.com/fupcode)  
> URL: https://fupcode.com/blog/posts/devops/problem-docker-timezone/  

