在PHP开发中,我们经常会在时间问题上被搞糊涂,比如我们希望显示一个北京时间,但是当我们使用date函数进行输出时,却发现少了8个小时。几乎所有的php猿类都必须对php中几个重要的时间转换等方法进行研究。本文就来梳理这些问题。

时间戳(timestamp)

GMT

在时间戳这个点上,它是一个概念,而不是具体的编程问题,是计算机世界通用的一种约定。时间戳是指格林尼治时间(GMT)1970年01月01日00时00分00秒到当前时间的总秒数。

GMT(也被称为世界时)是固定为本初子午线经过地区的时间,因此被作为时间参照物。

UTC

协调世界时(UTC)和GMT一样都是一种时间的参照物,但是他们的计算方法不同UTC是以原子时秒长为基础,在时刻上尽量接近于世界时的一种时间计量系统,从精度上讲,更加精确(自然也比GMT更精确),因此被称世界统一时间,世界标准时间,国际协调时间。

Unix时间戳

Unix时间戳是在计算机领域才有的,每一台电脑(服务器)在生产的时候,将GMT/UTC的1970年01月01日00时00分00秒作为起始值进行计算,得到的总秒数就是这个Unix时间戳。至于是GMT还是UTC意义并不大,因为GMT和UTC的1970年01月01日00时00分00秒是一致的,起点一致的情况下,运行的秒数也是一致的。

为什么要时间戳?因为从0开始运行的秒数永远相等,即使出现润秒,也并不影响时间戳。

在php中,可以通过time函数获取时间戳:

time();

但是你应该明白,time()获取的是,当前这台电脑(服务器)上的Unix时间戳。两台电脑可能这个时间戳并不相同,有的甚至相差几十秒。从理论上讲时间戳应该是一摸一样的,但是由于不同的电脑硬件出厂时的设定不同,也会导致GMT/UTC起始值稍有差异,甚至在计算每一秒时也有可能存在差异,这台机器上一秒的时间比另一台要长也是有可能的,时间久了,积累下来的时间差就会体现出来。但是,这种时间差一般不会超过几秒钟。

时区(Time Zone)

但是上面的time()的表述并不准确,因为我们在实践中经常遇到time()得到的值并不是我们想要的。对应的是,date()函数得到的值,也可能出乎我们意料。

什么是时区呢?也就是以GMT/UTC为参照物的时间偏移。

以GMT为参照物的时区

在传统的教材里,全球被划分为24个时区,首先基于经度,其次按照国家或地区,将每一个地区划分到某一个时区,这样可以避免时间上的混乱。在24时区划分之前,世界上的时间换算并没有准确的参照,比如中国人去英国,只能问当地人现在几点,然后拨自己的表来对。而当时区划分之后,中国人到了英国,只需要拨慢8小时即可。在时区划分之前,英国人跟中国人的时间可能并不是严格的8小时之差。

但为了照顾到同一个国家内时间的统一,大部分国家规定自己属于同一个时区,比如中国,统一规定为东八区,这样中国东部和西部可以采用同一个时间。毕竟没有必要大家一定要在早上6点看到日出,沿海城市5点看,乌鲁木齐9点看,并不影响大家的正常作息。

在php中,提供了大量的地区作为时区切换的标准,例如:

date_default_timezone_set('Asia/Shanghai');
echo date('Y-m-d H:i:s'); // 获得的是上海所在时区的时间

注意:PRC是中国的地区时标志,并不在Asia中,而是在Others里面找。

以UTC为参照物计算时区

但随着UTC取代GMT成为世界标准时后,时区的计算开始使用UTC作为标准。UTC+8代表东八区,UTC-11代表西十一区。

不过随着精度需求的提升,按大时区计算已经不能满足需求,0.5个时区也被普遍使用,比如UTC+7.5。

在PHP中,我们可以采用这种方式来切换时区。比如:

date_default_timezone_set('UTC');
echo date('Y-m-d H:i:s'); // 获取的是0时区时间

时区给PHP带来的影响

我们上面给出的代码并没有什么实际意义,因为你还不知道为什么要这样去做。实际上,php在使用date函数的时候,会依照所在时区去进行计算。

例如,你的服务器是放在英国的,而服务器的默认配置php.ini中没有规定时区,那么php就会以操作系统默认是时区作为时区进行输出,这就会导致这台服务器上的date()函数输出的时间是以UTC+0作为时区的,如果你的用户在中国,那么网站的访客看到的时间就会少8个小时。

而上面使用date()进行输出的时间,就是我们所说的本地时间

本地时间,其实是指服务器上的程序输出时间,date函数输出的时间依托Unix时间戳和时区,因此它一定是一个不准确的时间,因为Unix时间戳基本上都是不准确的,但是这个不准确是可以忽略的,严重的是时区的偏差。

造成php输出时间混乱的原因总结起来:

  • 使用默认的date函数的输出值
  • 在保存时间的时候使用调整过时区的时间,而输出时又调整了时区

第一点比较容易理解,比如默认存进去的时候存入的是time(),输出的时候使用date(),time()是没有错的,但是date()在输出的时候,时区和当前访客的时区对不上,从而导致输出内容的错误。

如何在PHP中保证输出时间的准确性?

我们想的更多的是如何保证时间的准确性问题。这要从多方面去考虑,输入输出的一致性与非一致性是一个很大的挑战,你需要把握好全局关系。

1.php.ini配置文件中规定时区

从php5.1.0开始,php.ini配置文件中支持设置一个date.timezome的值来规定默认的时区,找到它,并改为:

date.timezone = PRC

当然,PRC也可以用php官方给出的列表中的其他时区代表值表示。

这种配置的好处是,可以在所有的php代码中生效,坏处是灵活性差,而且大部分主机并不直接支持php.ini配置。

2. ini_set('date.timezone')

在php代码开头,可以使用ini_set函数来临时修改一些php的默认配置,可以:

ini_set('date.timezone','Asia/Shanghai');

这种方法的好处是比较灵活,需要配置时区的代码里才使用,把这个配置放置在一个共享文件里,可以使所有引用这个文件的php脚本都获得这个配置。坏处是有的主机不支持ini_set。

3.date_default_timezone_set

和ini_set函数一样,date_default_timezone_set函数也可以临时修改php配置。

date_default_timezone_set('Asia/Shanghai');

4.自己计算

当你在输出日期的时候,可以考虑自己调整时区,然后进行计算,将计算的结果格式化为日期再输出。首先,我们要搞清楚哪些是可变哪些是不可变。

可变:date()
不可变:time()、gmdate()

当你在输出一个日期的时候,如果使用date,就是可变的,但如果使用gmdate()就是不可变的,gmdate()永远把时区当做是UTC+0,即使你通过前面三种方法临时修改了时区,也不会影响gmdate的输出结果,而这个时候,其实你又知道你的访客所在的时区,所以,你可以自己计算一下:

// 方法1
date('Y-m-d H:i:s',strtotime(gmdate('Y-m-d H:i:s').' +8 hours'));
// 方法2(推荐)
gmdate('Y-m-d H:i:s',time() + 8*3600);

使用上面的两个方法,无论你的服务器处于什么时区,无论你是否使用date_default_timezone_set设置了新的临时时区,都不会影响结果,因为gmdate永远以UTC+0作为参照,根本不会理会你新设置的时区。甚至,你把你的这段代码,从非洲的服务器搬到中国的服务器上,它的结果也还是一样(忽略timestamp的微小误差)。

有一个有趣的现象是,我们可以通过一个动态的数字来控制date()是时区,而无需去设置时区,比如:

date('Y-m-d H:i:s',time() + n*3600)

其中的n则是时区,东八区就是+8,西五区就是-5。而我们却可以找出这个动态的n值,它和时区时时相关:date('Z')

date('Z')是一个军事级别的应用,它用于计算以秒为单位的时区偏移量,比如东八区,它的值就是8*3600,我们可以在time()的基础上减去这个值,得到一个比当前时间戳少时区偏移量的值,这个值在实际中没有任何意义,它不代表任何时间戳(或者说是当前时间n小时之前的时间戳),但如果我们再对这个时间戳进行date运算时,date会把n时区的偏移量加回来,这样就得到了一个固定的UTC+0的日期时间:

$gmt_date = date('Y-m-d H:i:s',time() - date('Z'));

它的效果其实和gmdate('Y-m-d H:i:s')相同,但算法上更加复杂。

同样的道理,我们以UTC+0作为基准,增加这个偏移量,反而可以得到我们想要的时区所在的时间:

$local_time = gmdate('Y-m-d H:i:s',time() + date('Z'));

但这和$local_time = date('Y-m-d H:i:s');没有任何结果上的区别。

选择你合适的时间进行保存

在前面的分析里面,你看到有一种情况比较乱,就是使用了调整时区后的时间进行保存,但是显示的时候,又进行时区调整,这导致显示错误。

推荐的一种时间保存方案,是只保存timestamp,也就是time(),它的值是固定的,不随着时区的调整而改变,即使更换了服务器,它的误差也很小,所以有利于今后将程序分发部署到不同的服务器上面。

而在自己显示的时候,可以确定一个方法,比如上面推荐的方法2作为输出:

function st_date($format,$timestamp = false) {$timestamp = is_numberic($timestamp) ? $timestamp : time();return gmdate($format,$timestamp + 8*3600);
}

这样就可以保证这段代码无论在哪里,都可以输出东八区的时间。

转自:http://www.tangshuang.net/2794.html

PHP中关于时间(戳)、时区、本地时间、UTC时间等的梳理相关推荐

  1. java 字符串转utc时间_在Java中将UTC时间转换为本地时区

    我知道这个主题已被殴打致死,但在搜寻了这个问题几个小时之后,我不得不问. 我的问题:根据客户端应用程序(iphone)的当前时区对服务器上的日期进行计算.客户端应用程序以秒为单位告诉服务器,其时区距G ...

  2. 修改mysql数据库服务器时间格式,修改本地mysql数据库时间格式

    修改本地mysql数据库时间格式 内容精选 换一换 云数据库 GaussDB(for MySQL)仅按使用情况付费,没有最低收费.GaussDB(for MySQL)对您选择的数据库实例.数据库存储和 ...

  3. php utc时间_PHP转换UNIX时间戳 UTC时间(TZ格式) 标准时间的方法 UNIX UTC GMT时间、本地时间互转...

    在PHP编程中经常会遇到各种不同格式的时间 比如: unix时间戳:1547740800 UTC时间:2019-1-18T00:00:00Z 标准时间:2019-1-18 00:00:00 以上这三个 ...

  4. linux时间戳 gps,gps时间(gps时间戳转换成utc时间)

    GPS时间系统 GPS系统是测时测距系统,GPS定位要求有高度精确的.稳定的和连续的观测时间,因此时间系统对GPS定位具有重要意义.时间系统与坐标系统一样,应. 通俗的讲,所以存在的时间系统全部由两部 ...

  5. linux 取消utc时间,ubuntu系统下禁用utc时间的设置方法

    前言 大家在安装双系统以后,发现进入win7和ubuntu系统以后,显示的时间不一致,后来发现是两个系统对硬件时间的看法不一致 原因如下 1.Windows会认为BIOS时间就是你的本地时间 2.ub ...

  6. WMware Workstation——时间和时区问题

    对于学习Linux的人来说,最常见的做法就是在WMware Workstation下安装Linux系统.在WMware Workstation可能会有几处导致时间.时区问题. UTC时间导致时间不一致 ...

  7. 谈谈对python中的日期、时间、时区的理解(1)

    文章目录 基本概念 GMT UTC DST TIMEZONE ISO 8601 TIMESTAMP 不知大家是否曾遇到过这种困惑,当一堆时间相关的概念混到一起时,就搞不清楚时间到底该怎么玩啦! 本系列 ...

  8. UTC时间、GMT时间、本地时间、Unix时间戳的区别

    1.UTC时间 与 GMT时间 UTC时间的英文全称:Universal Time Coordinated,中文名称:协调世界时.俗的理解为,这个时间是全世界通用的,即全世界都公用的一个时间.可以认为 ...

  9. php utc时间_PHP跨时区(UTC时间)应用解决方案_php技巧

    1.将程序内部时区设置为UTC时间.(UTC 也可以叫 GMT) PHP设置: date_default_timezone_set("UTC"); Yii设置: config/ma ...

  10. PHP时区设置,PHP时间问题

    在web项目中很多是以时间相关的,而且有些与时间的关系非常大!前段时间做了个天气预报15天查询(http://tqybw.net)的项目,功能和展示与时间设置非常紧密,现在将PHP时区设置,PHP时间 ...

最新文章

  1. 编译DirectShow Samples
  2. WCF服务支持HTTP(get,post)方式请求例子
  3. 雅虎核心业务售与Verizon:互联网先驱的时代终结
  4. 小白浅论JAVA数组中“for加强版”
  5. impala的工作原理的详解(图文)
  6. C/C++中函数指针的含义(转)
  7. Firefox for iOS 终于登陆中国
  8. React 中实现复制到剪切板功能
  9. 离散数学真值表(c语言编程实现)
  10. 智能控制器在风机及水泵中的应用
  11. 计算机画图星星怎么画,教你尺规作图画五角星!
  12. 关于xmind6图标组导入教程
  13. SEO人员应该突破的5大思想误区
  14. html心碎粒子特效,system-data.html
  15. 计算机二级考试-Java-模拟试题
  16. 大数据晋级之路(4)Hadoop生态系统体系架构及基本概念
  17. html中url英文全称,URL的英文全称
  18. ViT强势应用 | V2X基于ViT提出了一个具有V2X通信的强大协作感知框架
  19. SQL 增加或删除一列
  20. 群签名和环签名的区别_环签名与群签名

热门文章

  1. python图形界面开发用什么
  2. 不忘过去,不畏将来——我的2017
  3. 多元微积分_散度3.高维散度
  4. 计算机思维导论优课在线答案,吉大20秋《现代远程学习概论》在线作业题目【标准答案】...
  5. 池建强 Mac Tips
  6. Android踩坑小记:在onResume中申请权限
  7. 手持光谱仪与便携光谱仪分别是什么?
  8. 【合新通信】40G QSFP+光口转化10G SFP+光口
  9. IntelliJ IDEA必备插件
  10. 微众区块链携手西安交通大学,打造硬核课程