V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
lslqtz
V2EX  ›  问与答

在 PHP 中有什么方法能获取自 0001 年以来经过的秒数?

  •  
  •   lslqtz · 2017-08-13 01:43:06 +08:00 · 3741 次点击
    这是一个创建于 2666 天前的主题,其中的信息可能已经有所发展或是发生改变。
    具体是 0001 年 1 月 1 日 00:00:00 来经过的秒数...
    用其它函数好像都会有误差,有没有什么合适的方法来获取...
    第 1 条附言  ·  2017-08-13 02:35:56 +08:00

    已经写好了,和我想象的差了1秒... 有错误请指正一下w

    <?php
    date_default_timezone_set('UTC');
    function years_to_seconds($year) {
    	$s=0;
    	for ($i=0;$i<$year;$i++) {
    		if (($i % 100 == 0 && ($i % 400 == 0 && $i % 3200 != 0)) || ($i % 4 == 0 && $i % 100 != 0)) {
    			$s += 31622400;
    		} else {
    			$s += 31536000;
    		}
    	}
    	return $s;
    }
    $seconds=years_to_seconds(1969) + strtotime('2016-01-01 00:00:00');
    echo $seconds;
    ?>
    
    第 2 条附言  ·  2017-08-13 05:11:06 +08:00
    function years_to_seconds($year) {
    	
    	$s=0;
    	for ($i=1;$i<$year;$i++) {
    		if (($i % 100 == 0 && ($i % 400 == 0 && $i % 3200 != 0)) || ($i % 4 == 0 && $i % 100 != 0)) {
    			$s += 31622400;
    		} else {
    			$s += 31536000;
    		}
    	}
    	return $s;
    }
    

    改了下函数,这段函数和

    function years_to_seconds($year) {
    	return 31536000*($year-1)+(floor($year/4)-floor($year/100)+floor($year/400)-floor($year/3200))*86400;
    }
    

    相等

    39 条回复    2017-08-13 20:22:35 +08:00
    ovear
        1
    ovear  
       2017-08-13 01:44:36 +08:00   ❤️ 1
    http://php.net/manual/zh/function.date-diff.php

    date_diff — 别名 DateTime::diff()
    xfspace
        2
    xfspace  
       2017-08-13 01:45:16 +08:00 via Android
    timestamp
    lslqtz
        3
    lslqtz  
    OP
       2017-08-13 01:46:13 +08:00
    @ovear 之前看到过这个,好像有说不准确,先感谢
    lslqtz
        4
    lslqtz  
    OP
       2017-08-13 01:46:35 +08:00
    @xfspace Unix timestamp 是指 1970 年以后的秒数...
    ovear
        5
    ovear  
       2017-08-13 01:47:32 +08:00
    @lslqtz 那要不雇一个大学生帮你算一下。。。好像也不贵
    lslqtz
        6
    lslqtz  
    OP
       2017-08-13 01:49:34 +08:00
    @ovear 其实想自己算,但是。。真的麻烦
    ovear
        7
    ovear  
       2017-08-13 01:51:45 +08:00
    @lslqtz 有啥麻烦的,除了闰年还有啥。。
    ovear
        8
    ovear  
       2017-08-13 01:52:37 +08:00
    润秒要考虑进去的话,就百度加了几次闰秒
    lslqtz
        9
    lslqtz  
    OP
       2017-08-13 01:56:15 +08:00
    @ovear 感觉这么多年的闰年...头大
    试了试,只能精确到天数
    ovear
        10
    ovear  
       2017-08-13 01:56:52 +08:00   ❤️ 1
    @lslqtz 百度成熟的闰年算法。。
    lsylsy2
        11
    lsylsy2  
       2017-08-13 02:24:10 +08:00
    @ovear
    @lslqtz
    如果算到 0001 年的话,最大的问题是中间历法经过变动,严格来说要把那些一年不是 365/366 天的年代也算进去
    lsylsy2
        12
    lsylsy2  
       2017-08-13 02:30:47 +08:00
    另外 unix 时间戳是没有考虑闰秒的。然后你往前推到人类还没有定义闰秒的年代……
    所以获取“从历法的 0001 年以来经过的,2017 年物理学定义中的秒数”,误差可能是天级别( 24*60*60 秒)的;
    以我的知识估算了一下,准确到小时问题不大(将历史上的所有修改历法考虑进去,算出一个 0001 年到 1970 年的秒数,然后加上 unix 时间戳)
    极限可能是几十几百秒吧(两千年间人类没能观测到的闰秒累计起来)
    lslqtz
        13
    lslqtz  
    OP
       2017-08-13 02:35:11 +08:00
    @lsylsy2 我重新写了算了一下,和我想象的差了 1 秒...
    chairuosen
        14
    chairuosen  
       2017-08-13 02:36:43 +08:00
    别说闰秒,连小时,分钟也许都没有。你无法定义“ 0001 年 1 月 1 日 00:00:00 ”是哪一刻,所以无法得出结果。
    msg7086
        15
    msg7086  
       2017-08-13 04:28:48 +08:00   ❤️ 1
    @lslqtz 首先你这是从 0 年开始算的吧。第一年是 1 年哦,循环应该是从 1 到 year 吧。

    而且,这代码还用循环?

    function y($year) {
     $secs = 31536000 * $year;
     $leapdays = floor($year / 4) - floor($year / 100) + floor($year / 400) - floor($year / 3200);
      return $secs + $leapdays * 86400;
    }

    y(1969) # => 62135596800
    lslqtz
        16
    lslqtz  
    OP
       2017-08-13 04:34:41 +08:00 via iPhone
    @msg7086 所以我用的是 1969 啊…
    当时直接看了看顺手改了下 只顾着看没考虑性能…
    konakona
        17
    konakona  
       2017-08-13 04:43:47 +08:00
    @msg7086 你这没考虑闰年啊- -
    konakona
        18
    konakona  
       2017-08-13 04:44:06 +08:00
    @chairuosen 公元 1 年?
    konakona
        19
    konakona  
       2017-08-13 04:44:36 +08:00
    公元 1 年,属公元 1 世纪 00 年代。中国为辛酉年(鸡年),汉平帝元始元年。
    lslqtz
        20
    lslqtz  
    OP
       2017-08-13 04:48:43 +08:00
    去掉我上面那句话...
    大概得修,不过实际得出的结果影响
    lslqtz
        21
    lslqtz  
    OP
       2017-08-13 04:57:48 +08:00
    @konakona 我试了试,和我这段代码没有区别...
    Valyrian
        22
    Valyrian  
       2017-08-13 05:01:14 +08:00 via iPad
    两个时间戳减一下不就行了吗???
    lslqtz
        23
    lslqtz  
    OP
       2017-08-13 05:02:08 +08:00
    @msg7086 具体的计算思路是怎样的能讲讲不~ 说实话没看懂这算法...
    lzhr
        24
    lzhr  
       2017-08-13 05:03:36 +08:00
    SECONDS_PER_DAY, 86400
    DAYS_FROM_0_TO_1970, 719528

    好像没有零年
    lslqtz
        25
    lslqtz  
    OP
       2017-08-13 05:14:02 +08:00
    重新改了下函数,在 C#中得出的结果和 PHP 中 strtotime 里面的结果完全一样。
    我在 C#中用这段代码来测...
    Console.WriteLine(new DateTime(633979008000000000, DateTimeKind.Utc));
    在 PHP 中用这段代码来生成...
    <?php
    date_default_timezone_set('UTC');
    function years_to_seconds($year) {
    return 31536000*($year-1)+(floor($year/4)-floor($year/100)+floor($year/400)-floor($year/3200))*86400;
    }
    $seconds=years_to_seconds(1970) + strtotime('2010-01-01 00:00:00');
    $seconds*=10000000;
    echo number_format($seconds,0,'','');
    ?>
    chenqh
        26
    chenqh  
       2017-08-13 05:17:48 +08:00 via iPhone
    用现在的时间戳减去 01 年的时间戳不就好了吗
    chenqh
        27
    chenqh  
       2017-08-13 05:19:17 +08:00 via iPhone
    看错了忽略我吧
    msg7086
        28
    msg7086  
       2017-08-13 05:37:50 +08:00   ❤️ 1
    @lslqtz 1969 也是算到 1969 的年底啊,当然是 $i <= $year 咯。你要用$i < $year 的话要填 1970。
    思路的话你自己想想嘛。找出 20 以内 3 的倍数的个数,你怎么算的来着。

    @konakona 你说啥?
    lslqtz
        29
    lslqtz  
    OP
       2017-08-13 05:40:02 +08:00
    @msg7086 反正代码是拿来用的...没问题就行了,炸了再改(
    suman
        30
    suman  
       2017-08-13 07:33:29 +08:00
    1582 年 10 月 5 日~14 日是不存在的,楼主记得排除掉。
    GreatHumorist
        31
    GreatHumorist  
       2017-08-13 07:40:55 +08:00 via iPhone
    把 1970 年前的算出来做成常数,每次加时间戳不就行了?复杂度 O(1)
    yksoft1
        32
    yksoft1  
       2017-08-13 09:30:42 +08:00
    @suman 在东正教地区是存在的,俄国到十月革命之后才使用格里高利历。
    mrcn
        33
    mrcn  
       2017-08-13 11:14:23 +08:00 via Android
    0001 年到 1970 年的秒数是固定的对吧,然后再加上时间戳呢。
    lslqtz
        34
    lslqtz  
    OP
       2017-08-13 15:47:18 +08:00 via iPhone
    @mrcn 是固定的
    所以算出来就可以单独用了
    lslqtz
        35
    lslqtz  
    OP
       2017-08-13 15:48:06 +08:00 via iPhone
    @GreatHumorist 按这么说 性能还真不重要…
    geelaw
        36
    geelaw  
       2017-08-13 16:53:19 +08:00
    这楼里面怎么这么多发明历法的?

    不要尝试这种无意义的问题
    mrcn
        37
    mrcn  
       2017-08-13 16:54:01 +08:00 via Android
    @lslqtz 所以可以纸笔用数学方法直接算出,保存为常量
    lslqtz
        38
    lslqtz  
    OP
       2017-08-13 18:12:08 +08:00
    @geelaw 能解决问题的方法就是有意义的。
    @mrcn 用代码算可能更快一点...
    geelaw
        39
    geelaw  
       2017-08-13 20:22:35 +08:00
    @lslqtz 那你没看懂我的意思,我的意思是问题本身是无意义的,更术语的说法是你的问题不是 well-formed/well-asked/well-defined.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2769 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:30 · PVG 17:30 · LAX 01:30 · JFK 04:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.