程序员如何处理好时区问题

写国际化的程序,经常会遇到两种问题:字符编码、时间问题。今天我们就聊聊程序中如何处理时间问题。

首先,要了解一些基本的概念,只有对概念有清晰的掌握,才能明白解决方法。

基本概念

GMT时间:格林尼治标准时间(英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台当地的平太阳时,因为本初子午线被定义为通过那里的经线。

由于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治平时基于天文观测本身的缺陷,已经被原子钟报时的协调世界时(UTC)所取代。

UTC时间:协调世界时(英语:Coordinated Universal Time,法语:Temps Universel Coordonné,简称UTC)是最主要的世界时间标准,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。

对于大多数用途来说,UTC时间被认为能与GMT时间互换,但GMT时间已不再被科学界所确定。

UNIX时间戳:Unix time又叫POSIX time或UNIX Epoch time,是从UTC时间1970年1月1日起到现在的秒数,不考虑闰秒,一天有86400秒。

时区:时区是地球上的区域使用同一个时间定义。世界各个国家位于地球不同位置上,因此不同国家特别是东西跨度大的国家日出、日落时间必定有所偏差。这些偏差就是所谓的时差。

闰秒:闰秒是在协调世界时(UTC)中增加或减少一秒,使它与平太阳时贴近所做调整。在UTC时间中,有时会出现一分钟有59秒或61秒。

夏令时:美国原本于每年4月的第一个星期日凌晨2时起至10月的最后一个星期日凌晨2时实施夏时制;但经美国国会2005年通过的能源法案,自2007年起延长夏时制,开始日期从每年4月的第一个星期日,提前到3月的第二个星期日,结束日期从每年10月的最后一个星期日,延后到11月的第一个星期日。美国夏时制实行与否,完全由各州各郡自己决定。

时间格式的标准:参考ISO_8601日期格式标准 https://zh.wikipedia.org/wiki/ISO_8601。例如:2004-05-03T17:30:08+08:00 在时间前面加上大些字母T,要标明偏移的时区时间。

概念解读

通过上面的概念介绍了解到,GMT就是0时区的时间,以前是标准,但现在国际上已经用UTC取代他了。在写程序时,可以认为UTC和GMT是等价的。为了严谨只需要关心UTC时间。

UNIX时间戳是程序中最常用的,他的特点是和UTC时间的1970年1月1日到现在的秒数,和时区无关,无论在地球上的那个角落,同一时刻,UNIX时间戳都是一样的。是一个通用的时间偏移度量,计算每个时区当地时间时,都可以用时间戳推算出来。

不同时区的时间,都用UTC时间的偏移来计算。例如北京是东八区,比UTC时间快8个小时,所以计算北京时间,就在UTC时间的基础上加8个小时实现。

我们在调用系统函数展示时间时,底层是根据UNIX时间戳转换为UTC时间,再加上偏移的小时数,就得出了程序要用的当地时间。

UNIX时间戳可以映射到每个时区的当地时间,如果程序涉及到两个时区的时间转换,最好的方法是存储UNIX时间戳,在使用的时候再做转换。

在各种语言的函数库中,都已经定义了时间时区转换的函数。在使用时,还有一点要注意「时区偏移(time offset)」和「时区地区(time zone)」是两个不同的概念。

偏移是一个数学上的值,直接能计算出时间。时区地区,会根据当地的法律规则,来得出最终的时间,混入了人为的规则。

例如:
在夏令时时,北京和纽约时差是12个小时,但是当夏令时结束时,北京和纽约的时差是11个小时。如果一直用固定的时间偏移,就会计算出错。如果用指定的地区当参数,就会根据当地规则返回正确时间。

具体例子见代码:

<?php                                                                              

date_default_timezone_set(‘Asia/Shanghai‘);
$d=strtotime("2018-11-04 13:00:00");
echo "Beijing " . date("Y-m-d h:i:sa", $d) . "\n";                                 

date_default_timezone_set(‘America/New_York‘);
echo "NewYork " . date("Y-m-d h:i:sa", $d) . "\n";                                 

echo "\n";                                                                         

date_default_timezone_set(‘Asia/Shanghai‘);
$d=strtotime("2018-11-04 14:00:00");
echo "Beijing " . date("Y-m-d h:i:sa", $d) . "\n";                                 

date_default_timezone_set(‘America/New_York‘);
echo "NewYork " . date("Y-m-d h:i:sa", $d) . "\n";                                 

echo "\n";                                                                                                                                          

date_default_timezone_set(‘Asia/Shanghai‘);
$d=strtotime("2018-11-04 15:00:00");
echo "Beijing " . date("Y-m-d h:i:sa", $d) . "\n";                                 

date_default_timezone_set(‘America/New_York‘);
echo "NewYork " . date("Y-m-d h:i:sa", $d) . "\n";                                 

输出结果

Beijing 2018-11-04 01:00:00pm   //没结束夏令时时,时差12个小时
NewYork 2018-11-04 01:00:00am

Beijing 2018-11-04 02:00:00pm   //夏令时切换,时差为11个小时
NewYork 2018-11-04 01:00:00am

Beijing 2018-11-04 03:00:00pm
NewYork 2018-11-04 02:00:00am

总结

  1. 涉及到多个时区的转换,统一使用unix时间戳存储或交互,或者使用带有时区信息的字符串。
  2. 尽量在上层的代码层面修改时区配置,不要修改系统或软件的配置,防止其他程序因为修改受到影响。

本质:时区概念是上层人为转换的概念,程序的逻辑不要依赖于他,要有个统一的时刻值概念来衡量真实的时间(例如UNIX时间戳),然后在上层做转换。

参考

https://zh.wikipedia.org/wiki/%E6%A0%BC%E6%9E%97%E5%B0%BC%E6%B2%BB%E6%A8%99%E6%BA%96%E6%99%82%E9%96%93

https://en.wikipedia.org/wiki/Unix_time

https://zh.wikipedia.org/wiki/%E5%8D%8F%E8%B0%83%E4%B8%96%E7%95%8C%E6%97%B6

https://zh.wikipedia.org/wiki/%E6%97%B6%E5%8C%BA

https://www.cnblogs.com/zihanxing/articles/6224263.html



转载请注明来源:程序员如何处理好时区问题

本文链接地址:https://www.owenzhang.net/blog/197.html

原文地址:https://www.cnblogs.com/owenandhisfriends/p/10015572.html

时间: 2024-10-18 21:18:25

程序员如何处理好时区问题的相关文章

程序员该如何处理人际关系

程序员该如何处理人际关系,以下峰峰为您分享: 良好的人际关系是一个人获得幸福感的重要指标之一,如果不能维护好与家人.朋友.同事的关系,工作再出色也无法让你快乐. 很多人对程序员的印象都是内向.呆板.邋遢.闷骚,然而这并不是真实的程序员.导致这种情况的原因大致是因为:编程的工作需要记忆很多程序逻辑,必有高度集中精力,因此工作中会尽量少跟人说话,工作后需要大量的时间休息.其次,对于普通人来说,编程语言太高深,他们工作的内容无法跟你分享,导致聊天话题减少,这是很正常的,并不是他们不喜欢聊天. 如果你有

优秀程序员是如何处理糟糕代码的

优秀程序员是如何处理糟糕代码的 可能你一行不好的代码也从来没有写过.这是有可能的,但在现实中又不太可能. 现实情况是,和这个星球上的其他所有程序员一样,你会产出安全漏洞.UI元素偏移,等等等等的代码.这并不能说明你是一个不好的开发人员.只是因为你是人类而已--一种不可避免会犯错的生物. 正是这种每个开发人员都有的"人性"缺陷,驱使那些优秀的开发人员敢于承担代码和底层基础架构的不足,有准备有计划地行动.下面是他们将做的事情. 假设 几年前,Netflix开源了Chaos Monkey和S

如何处理前任程序员留下的代码

作为软件工程师不可避免会遇到的一个场景是:我们在改变或添加一个功能到不是我们创建的.我们不熟悉的.与我们负责的系统部分无关的代码中时,会遇到麻烦.虽然这可能会是一个繁琐而艰巨的任务,但是由于使用其他开发人员编写的代码有很大的灵活性,所以我们可以从中得到大大的好处,包括增加我们的影响范围,修复软件腐烂以及学习我们以前不了解的系统部分(更何况,还可以学习其他程序员的技术和技巧). 考虑到使用其他开发人员编写的代码既有其厌烦之处,又有其优势所在,所以我们必须小心不要犯一些严重的错误: 我们的自我意识:

为什么国外程序员爱用 Mac?

from http://www.vpsee.com/2009/06/why-programmers-love-mac/ Mac 在国外很受欢迎,尤其是在 设计/web开发/IT 人员圈子里.普通用户喜欢 Mac 可以理解,毕竟 Mac 设计美观,简单好用,没有病毒.那么为什么专业人士也对 Mac 情有独钟呢?从个人使用经验来看我想有下面几个原因: 1.Mac OS X 是基于 Unix 的.这一点太重要了,尤其是对开发人员,至少对于我来说很重要,这意味着Unix 下一堆好用的工具都可以随手捡到.

StackOverflow程序员推荐:每个程序员都应读的30本书

“如果能时光倒流,回到过去,作为一个开发人员,你可以告诉自己在职业生涯初期应该读一本,你会选择哪本书呢?我希望这个书单列表内容丰富,可以涵盖很多东西.” 很多程序员响应,他们在推荐时也写下自己的评语.以前就有国内网友介绍这个程序员书单,不过都是推荐数 Top 10的书.其实除了前10本之外,推荐数前30左右的书籍都算经典,伯乐在线整理编译这个问答贴,同时摘译部分推荐人的评语.下面就按照各本书的推荐数排列. 1. <代码大全>史蒂夫·迈克康奈尔 推荐数:1684 “优秀的编程实践的百科全书,&l

一个合格的程序员应该读过哪些书

编者按:2008年8月4日,StackOverflow 网友 Bert F 发帖提问:哪本最具影响力的书,是每个程序员都应该读的? “如果能时光倒流,回到过去,作为一个开发人员,你可以告诉自己在职业生涯初期应该读一本,你会选择哪本书呢?我希望这个书单列表内容丰富,可以涵盖很多东西.” 很多程序员响应,他们在推荐时也写下自己的评语.以前就有国内网友介绍这个程序员书单,不过都是推荐数 Top 10的书. 其实除了前10本之外,推荐数前30左右的书籍都算经典,笔者整理编译这个问答贴,同时摘译部分推荐人

程序员到项目经理:从内而外的提升

转自:http://www.cnblogs.com/watsonyin/archive/2012/09/10/2679528.html 目录 从程序员到项目经理(一):为什么要当项目经理 从程序员到项目经理(二):升职之辨 从程序员到项目经理(三):认识项目经理 从程序员到项目经理(四):外行可以领导内行吗 从程序员到项目经理(五):程序员加油站,不是人人都懂的学习要点 从程序员到项目经理(六):程序员加油站 — 懂电脑更要懂人脑 从程序员到项目经理(七):程序员加油站 — 完美主义也是一种错

黑马程序员——————&gt; 异常处理之抛出

------- android培训.java培训.期待与您交流! ---------- java的异常被分类为两大类,Checked异常和Runtime异常(运行时异常).所有的RuntimeException类及其子类的实例被称为Runtime异常:不是RuntimeException类及其子类的异常实例则被称为Checked异常. 对于Checked异常的处理方式有如下两种. 1:当前方法明确知道如何处理该异常,程序应该使用try...catch块来捕获该异常,然后在对应的catch块中修复

程序员内部培训

1.前言 虽然题为培训,但我还是想说一句,程序员其实不需要培训,只需要指点.原因有三: 程序员的工作都必须去实践,几乎没有纯理论的领域. 由于互联网的开放性,程序员能找到大量的资源自学. 随着实践深入,会自然地遇到一些问题.解决这些问题除了靠智力外,大部分只需要知道答案的大致方位就能用时间来消灭掉. 大牛之所以能成为大牛,就是知道了很多答案存在的地方以及发现这些地方的方法.优秀的程序员培训师懂得教方法而不仅是教答案.可惜很多培训师不是这样的,公司内部的培训流于形式,大家听完后就知道这是个很牛b的