公司是做全球市场的,所以经常在产品对需求,研发时遇到时区的问题,每次都很含糊,那这次就索性调研下吧。
先说结论:
- 总原则:显示跟存储分离。
- 存储,以及后端服务之间交互时最好都使用时间戳;
- 前端显示时根据用户本地时区对时间戳转换。
- 后端定时任务: 如果涉及当地重要时间的,使用当地时区配置,否则可以默认使用北京时间,方便国内研发同学辨识。
- 后端服务之间交互: 使用时间戳; 或者时间格式 + 时区。
基于上述几个结论,下面看几个交互环节的建议。
1 MySQL中的时间存储
MySQL支持几种时间类型,datetime、timestamp,但是最好都使用bigint, 存储时间戳。 因为dateTime 跟TimeStamp 存在如下的问题:
- DateTime类型字段,MySQL存储时不存时区信息,并且怎么存就怎么取,不做任何处理和转换。所以时区timeZone1的server1插入MySQL一条记录后,时区timeZone2的server2读取出来的时间就不对了。这里只能将所有的server的时区设置为一样的,或者在数据库表中添加一个字段存储时区信息
- TimeStamp类型字段,这个比较特殊。当server创建connection时,可以在数据库URL中手动指定时区信息,即不同时区的server连接MySQL时,指定connection时区使用自己所在时区。当MySQL处理不同的connection时,就有了时间字符串和发出请求的时区,然后转换为UTC时间进行存储。从MySQL中读取时也是基于connection的时区设置进行转换。但是如果不指定connection时区,那么MySQL就将存储的UTC时间,按MySQL服务器所在时区进行转换和展示或者传输,此时若MySQL服务器和server的时区不一致,就会出现时区问题。
2 服务器到客户端
一般这种情况下,服务器会把时间戳给到客户端,然后客户端根据用户本地时区进行时间显示。 如果需要在客户端强制显示某个时区的内容,也可以把时区一并传给客户端。
3 客户端到服务器
客户端给服务器时,建议直接转换为时间戳给到服务端。至于服务端怎么处理时间戳,由服务端自己决定。
4 服务A跟服务B交互
最好也是使用时间戳。如果使用时间,而服务A跟B的时区不一致,则就会产生问题。而使用时间戳就不会有这个问题。
如果非得传时间,则需要指定时区。
5 服务器到MySQL
同服务之间的传输,也是建议使用时间戳。
6 定时任务
如果涉及当地重要时间的,使用当地时区配置,比如印度某个特定的节日,需要针对节日做某些任务的定时导入;
如果不涉及当地重要时间,则可以默认使用北京时间,方便国内研发同学辨识。
7 多个时区转换
以UTC时间为基准,然后加减时区。本质:时区概念是上层人为转换的概念,程序的逻辑不要依赖于他,要有个统一的时刻值概念来衡量真实的时间(例如UNIX时间戳),然后在上层做转换。
8 参考文献
1、显示与存储分离
4、时区转换