发布网友 发布时间:2022-11-25 04:05
共1个回答
热心网友 时间:2023-10-08 18:06
摘要:本文总结几类项目中跟时区相关的问题,给大家分享一些基本的时区知识,以及如何在软件开发和测试中注意考虑时区因素,以避免因时区而导致系统功能的问题。
(原文: 时区那些事儿 )
蓝鲸项目的小Q和小D说的是啥呢?下面先来借助维基百科的解释来介绍时区和UTC的概念:
原来小Q和小D所在的蓝鲸项目正在开发一个全球性的系统,用户处于世界各地的不同时区。
系统的工单处理流程中每个任务的完成因为有先后依赖关系,当时记录的是完成时刻的UTC时间,以防不同时区的用户完成依赖任务的时候产生冲突。
比如:处于UTC+0800时区的用户S在当地时间 2019-02-28 09:30 处理了任务1,系统记录的时间是 UTC 2019-02-28 01:30 ,接下来处于UTC-0800的用户G在当地时间 2019-02-27 18:20 来处理任务2(必须晚于任务1完成),系统记录的是 UTC 2019-02-28 02:20 ,这个时间就不会有问题。
在处理某个任务的时候如果发现有信息缺失,需要记录发现和收集到缺失信息的时间(可以是过去时间,由用户输入),而这个发现和收集完成的时间一般都是同一个用户来记录,本身不会有时区问题,另外这个时间跟工单处理流程中的任务完成时间并没有特别直接的关系,就对缺失信息部分只记录由用户输入的日期,而且是直接记录用户当地时间的日期,并没有记录时分秒,也没法根据UTC进行转换。
这样,同一个日期,比如,在东部时区的 2019-04-28 可能就是西部时区的 2019-04-27 ,在西部时区的 2019-04-28 可能就是东部时区的 2019-04-29 ,前后有相差一天的可能性。
但是,在做到KPI功能的时候,计算KPI需要结合工单任务处理时间和缺失信息记录时间,由于没有考虑时区问题,不同时区可能会造成KPI有一天的误差。
这又是为什么呢?大家都在焦急地等待小D的解释。
原来,对于这种没有时分秒要求的时间,我们系统统一用当天中午UTC的12:00存入DB,这样做的原因是保证-12~+12时区内都不会有问题,换算以后都是当天,但是没有考虑到正负13、14区的情况。
下面我们来举例说明为什么东14区的会有问题。
假设用户A和用户B分别处于东12区和东14区,A和B分别在当地时间的2019年04月28日的上午9:00签订了合同,那么系统记录的时间都是 UTC 2019-04-28 12:00 ,在用户A的页面上显示的日期是 2019-04-28 ( UTC 2019-04-28 12:00 转换东12区的时间是 2019-04-28 24:00 ,这个时间的日期还是4月28日),而在用户B的页面上显示的日期应该是 2019-04-29 ( UTC 2019-04-28 12:00 转换东14区的时间是 2019-04-28 26:00 ,也就是 2019-04-29 02:00 ,这个时间的日期变成了4月29日)。
如下表,用户A、B、C、D的合同签订时间都是当地时间2019年04月28日的上午9:00:
同理,用户C和D处于西部时区,从上表我们可以看到处于-12的C的时间是跟实际日期一样,而处于-13的用户D的时间则比实际时间早了一天,也是有问题的。
至此,我们明白了为什么东14区会引起系统功能有问题。但是,一直以来以为时区都在正负12之间,为什么会有大于+12的时区呢?原来小D是早就知道的,他给我们解释了是下面两个原因:
其实,时区还有很多有意思的,有偏移量是半个小时的(如印度),还有45分钟的(如尼泊尔),不一定都是整点。更多详情可以参考维基百科的 时区列表 。
这个问题听起来很简单,直接在DB里把对应的时区改一下就ok了。可是,正当小D准备去改数据的时候,发现了一个崩溃的事情:伊斯坦布尔和明斯克还跟另外两个地区的时区是绑定在一起的,见下图。当前系统中已经设置好的一些会议,没法判断真正需要的是哪个地区对应的时区... 已有数据无法修复!
在此先不解释如何修复的数据问题。
当时,我们正好要把时区引入到另外一个新系统,考虑到避免再出现类似的情况,采用了一个新的库,那就是每个地区对应一个时区。比如:GMT+08:00分别有上海、乌鲁木齐、重庆、香港、新加坡等时区。
原来,这个时区表示法里时区名字都是用“区域/位置”来表示,比如“Asia/Shanghai”,而前面的“(GMT+08:00)”是表示相对于GMT的一个偏移量。前面对话中提到的“Etc/GMT-8”只是时区名字而已。那为什么叫这么奇怪的名字呢?
下面引用 维基百科 的解释来说明:
对于国际化的软件系统来说,时区还是需要特别关注的。根据所经历项目出现的时区相关问题,尝试总结以下几点供大家参考。
开发方面
测试方面