国际版多时区设计方案【转】
用户场景
国际版中各个仓库分属不同的城市,不同的城市所在时区不同,基于各个角色对数据的使用情况不一样
主要的用户场景
库内作业人员,仓库是纽约仓,时区是UTC-05:00,查询2017-12-1到2017-12-10的仓库入库单。即查询的是2017-12-1 00:00:00-05:00 到 2017-12-10 23:59:59-05:00 时间区间内创建的入库单。在查询结果显示的时候,时间数据也需要转换到纽约时区。
上游系统,比如OMS的系统调用。客户拥有两个仓库,分别在不同的城市。比较典型的是下单时间。下单时间由客户的ERP系统创建,对于不同仓库的订单,在各自的仓库内展现时,是按仓库所在城市来显示。
跨仓库的报表。勾选多个仓库,执行查询时,展示的时间,仍是以各自仓库所在城市时区展示。
操作仓库无关的资源。比如域内的用户资源。比如域管理员新建用户账户,同时要设置该用户的有效时间为2018-11-10 ~2018-11.15日,这个是依据客户端时区设置的。
设计方案
为了更好的讨论问题,对几个时区做下约定:
简称 | 说明 |
---|---|
localtime,localzone | 表示客户端时间和时区 |
whtime,whzone | 表示仓库时间和时区 |
apptime,appzone | 表示应用服务器的时间和时区 |
dbtime,dbzone | 表示数据库的时间和时区 |
3rdtime,3rdzone | 表示第三方系统的时间和时区,如GOMS或ERP |
按照以上的场景介绍,localzone只有在操作域资源的时候会涉及。在操作仓库资源的时候,均使用whzone。
appzone和dbzone均会设置成UTC+00:00,因为timestamp存储范围的原因,故不考虑。所有时间数据均保存为datatime。3rdzone则依赖实际情况,可能和appzone相同,也可能不同。
第一种方案是所有的时间均转化为UTC+0的时间再保存。第二种方案比较取巧,在保存的时候就考虑之后的显示,比如在纽约仓库的操作是2017-12-26 15:00:00-05:00 这个绝对时间发生的,保存的时候保存为2017-12-26 15:00:00-00:00,所以在保存的时候会有2017-12-26 15:00:00-05:00~2017-12-26 15:00:00-00:00的转化操作。
场景 | 方案1(记录UTC0时间) | 方案2(记录仓库时间) |
---|---|---|
订单创建时间 | 后台生成系统时间(appzone) | 1.获得应用服务器当前时间(apptime:2017-12-26 15:00:00+00:00)2.获得订单对应仓库的时区(whzone:+08:00)3.将apptime进行时区偏差处理,获得时间2017-12-26 23:00:00+00:00 |
订单下单时间(3rdzone=appzone) | 不需要转化 | 1.获得订单对应仓库的时区(orderTime: 2017-12-26 15:00:00+00:00 whzone +08:00)2.将下传的订单时间转化为仓库本地时间(whtime:2017-12-26 23:00:00+00:00) |
订单下单时间(3rdzone!=appzone) | 将上游系统时区转化到WMS时区(appzone) | 1.将上游系统时区转化到WMS时区(orderTime: 2017-12-26 15:00:00+08:00 3rdzone: +08:00 appzone:+00:00)2.获得订单对应仓库的时区(whzone: -05:00)3.将下传的订单时间转化为仓库本地时间(whtime:2017-12-26 2:00:00+00:00) |
仓库操作,查询条件中有时间 | 1.将查询时间转化为UTC0时间(whzone->appzone)(2017-12-26 12:00:00-05:00 ->2017-12-26 17:00:00-00:00) | 1.不需做转化其实还是需要转化的,除非客户上传的是不带时区的字符串,服务器当0时区的来处理 |
时间数据展示 | 1.将UTC0时间转化为仓库时间(appzone->whzone)(2017-12-26 17:00:00-00:00->2017-12-26 12:00:00-05:00 ) | 1.不需要转化.其实还是需要转化的,除非服务端输出的是不带时区的字符串,客户端直接显示字符串 |
另外,在时间格式化的问题上,也存在两种意见,一种是前台处理,一种是后台处理。如果上面采用方案2,那么只能采用后台处理,因为在方案2中,客户端是不会使用仓库时区数据的。客户端服务端之间交互时,使用的都是不带时区的字符串。所以在讨论是前台处理还是后台处理的时候,是假设上面采用了方案1.
场景 | 前台处理 | 后台处理 |
---|---|---|
登录时 | 1.后台给前台offsite = whzone - appzone。比如前台的仓库是纽约,则偏差是 -5h | |
仓库操作,查询条件中有时间 | 1.前台将查询条件依据offsite处理成long。2.后台用long生成Date对象 | 1.前台上传时间字符串2.后台获取仓库的时区信息3.转化为UTC0的时间 |
时间数据展示 | 1.后台返回long。2.前台依据offsite,转化为要显示的字符串 | 1.获取仓库的时区信息。2.转化为仓库的时间字符串 |
优点 | 1.后台处理不涉及任何时间转换处理,均是utc0的时间。2.前台能更好的结合多语的格式配置。3.更好利用富客户端的计算资源。 | |
缺点 | 1.客户端需要处理whzone,localzone,以及appzone之间的转化。在登录的时候,会返回whzone和appzone的偏差值,客户端需要使用该偏差值处理localzone |
原文地址:https://segmentfault.com/a/1190000012611095