时区处理总结
我司业务分布在跨时区的多个国家,我在日常积累了较多的时区处理经验,在此分享一下
首先基本概念,时间分为2种
- datetime,这是给人读的时间,分时区。如2000-1-1 12:00:00 gmt
- timestamp,这是unix时间戳,从1970-1-1开始的秒数,之前为负数。全球统一,无时区。如1495079384
时间戳和时间的相互关系
- 全球时间戳是一样的,比如1495079384在哪里都是这个值,只不过它在北京时区是2017/5/18 11:49:44,而在莫斯科时区却是2017/5/18 06:49:44
- 时间和时间戳可以相互转化,都依赖时区。比如上面莫斯科在utc+3而北京在utc+8,所以莫斯科比北京慢5个小时
数据统计的影响
- 时区对数据影响是很大的,尤其涉及到数据分析时,需要小心处理时区。各种数据库都有相应的转换方法
- 举个例子。比如收入表,入库时间字段timer是utc时间(如:2015-1-1 12:15:11),而你要统计莫斯科2015-1-2的一天的收入。那么直接where timer between '2015-1-2' and '2015-1-3'所得到的结果,是有问题。因为莫斯科比utc快3个小时,所以这个结果实际统计的是莫斯科1-2日3点开始到1-3日3点结束的时间短,结果比真实数据少了3小时当天,并多了3小时第二天的。
- 正确的做法,是在where里将timer转为莫斯科时间,如 where timer at time zone 'utc+3' between ... and ... (in postgre sql)
服务器api处理
- 个人建议,api里所有时间参数,统一用timestamp,可以毫秒也可以秒。这样不用考虑时区,适合全球化部署。而且时间戳比时间,在格式上更容易处理
- 如果一定要用时间来传参和入库,建议统一用utc
浏览器javascript的处理
- 所有form input组件,无论h5原生的input type=datetime-local还是datepicker,时间就是字面量。比如输入了2000-1-1 10:00,拿这个value就是这个本身,没有时区
- 用new Date来生成时间戳,如new Date('2000-1-1 10:00').getTime() 这个结果跟你打开浏览器的时区有关。不同的时区,执行结果是不同的。跟服务器位置无关,因为js是客户端执行
sort of, I have some experience in the domain of database(MySQL/mongo), java, python, front-end, etc. I'll willing to give and accept bits of help from others.
now base in Singapore.