zoukankan      html  css  js  c++  java
  • 坑~夏令时冬令时引发的时间换算问题

    起因

    最近接触到一些国外的项目,由于国内外有时差这个东西,对于某些基础数据存到数据库的时候需要记录时间,为了方便,这里采用了时间戳(int或者timestamp)记录。由于时间戳全球都是一样的,需要的时候根据时区进行转换就能够拿到当地的时间。

    嗯~ o(* ̄▽ ̄*)o,这样看起来确实没什么毛病。众所周知,一天有24小时,换算成秒就是:24*60*60=86400秒。

    然而,我在某次使用 MySql 的 FROM_UNIXTIME 发现一个问题,两个时间相差86400秒,但是格式化之后却不是相差一天!!!

    假设北京时间2019年11月25日 12:00:00,对应的时间戳是:1574654400,照理说这个时间戳加上一天86400秒,理论上就是北京时间2019年11月26日 12:00:00,事实上确实如此,国内的话这么算确实没什么问题,但是如果是国外时区的话,那可能会出问题。

    由于国外部分国家有夏令时冬令时之分(具体下面会细说),直接加上86400秒可能会有问题。

    感兴趣的可以拿1572764400(太平洋时间2019-11-03 00:00:00,单位:)这个时间戳验证下

    拿代码演示下:

    PHP:

    <?php
    
    echo "PST时区的时间
    ";
    date_default_timezone_set('PST8PDT');
    echo date('Y-m-d H:i:s',1572764400);
    echo "
    ";
    echo date('Y-m-d H:i:s',1572764400+86400);
    echo "
    ";
    
    //换个时区
    echo "换成上海时区看看
    ";
    date_default_timezone_set('Asia/Shanghai');
    echo date('Y-m-d H:i:s',1572764400);
    echo "
    ";
    echo date('Y-m-d H:i:s',1572764400+86400);
    echo "
    ";

    运行结果:

    PST时区的时间
    2019-11-03 00:00:00
    2019-11-03 23:00:00
    换成上海时区看看
    2019-11-03 15:00:00
    2019-11-04 15:00:00

    明明是同一个时间戳,都是加上86400(一天),为什么在上海这个时区是第二天,而在PST(美国太平洋时区)只加了23小时?神不神奇!意不意外!

    为了弄清楚这个问题,首先得先了解下什么是夏令时,什么是冬令时

    夏令时

    夏令时,表示为了节约能源,人为规定时间的意思。也叫夏时制,夏时令(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,在这一制度实行期间所采用的统一时间称为“夏令时间”。

    一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。[1]

    冬令时

    有夏令时就会有冬令时。高纬度和中纬度的许多国家在夏季到来前,把时针拨快一小时,新的时间就是夏令时,到下半季秋季来临前,再把时针拨回一小时,即形成冬令时。 [2] 

    夏令时和冬令时的影响

    拿美国来说,美国各个地区的时间都不同,不像中国一样统一使用北京时间,美国一般以三月份第二个周日凌晨两点当成夏季的开始,十一月份第一个周日的凌晨两点当成冬季的开始。

    所以在每年的三月份第二个周日凌晨两点过后,时间就会往前调快一个小时;同理,十一月份第一个周日把这一个小时调回来

    你也可以理解成美国那边,一年里面有一天只有23小时(夏天开始那一天),有一天有25小时(冬天开始那一天),其他时间每天都是24小时。

    所以你会发现,夏天的时候,中国的北京时间(东八区)与美国太平洋时区(西八区)的时差是15小时,而到了冬天却变成16小时

    解决方案

    回到开头那个问题,如果我们想直接算第二天,直接加上86400(一天)可能在其他国家就会有我上面那个夏令时和冬令时时间换算的问题,要如何避免呢?首先能够确定的是,直接加上86400是不可取的,如果加上一天能否行得通

    PHP:

    <?php
    
    echo "PST时区的时间
    ";
    date_default_timezone_set('PST8PDT');
    echo date('Y-m-d H:i:s',1572764400);
    echo "
    ";
    echo date('Y-m-d H:i:s',1572764400+86400);
    echo "
    ";
    
    echo "--------------------------
    ";
    echo date('Y-m-d H:i:s',1572764400);
    echo "
    ";
    echo date('Y-m-d H:i:s',strtotime('+1 day',1572764400));
    echo "
    ";

    运行结果:

    PST时区的时间
    2019-11-03 00:00:00
    2019-11-03 23:00:00
    --------------------------
    2019-11-03 00:00:00
    2019-11-04 00:00:00

    可以看出,不直接加上86400,直接在日期上加上一天是完全没问题的。

    JavaScript:

    var date = new Date(1572764400*1000);
    date.setDate(date.getDate()+1);
    var timestamp = Math.round(date.getTime()/1000);

    注意:JS的时间戳是毫秒!!!

    结论

    在经济全球化快速发展的今天,在软件开发的过程中,尽量养成习惯,由于夏令时和冬令时不是固定的,开发在时间计算上应该慎用86400进行加减运算,时间计算请直接对日期进行加减,展示时间给用户看的时候尽量结合当地时间,结合夏令时和冬令时计算出准确的当地时间,避免产生不必要的分歧。

    参考:

    [1]. 百度百科-夏令时

    [2]. 百度百科-冬令时

  • 相关阅读:
    今天实现了 沿路径移动
    enum类型的本质(转)
    (转)成为优秀技术人员的两点建议
    深入理解 C# 协变和逆变
    web通信
    ajax入门(复习)
    git版本管理工具的使用
    在asp.net 中使用httpmodules对网页进行处理
    asp.net http概念原理复习
    web page复习笔记
  • 原文地址:https://www.cnblogs.com/lyc94620/p/11930427.html
Copyright © 2011-2022 走看看