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

尴尬了,我连根据秒数来计算天数差值都搞不定,求解!

  •  
  •   wl879 · 2017-06-22 02:52:13 +08:00 · 3978 次点击
    这是一个创建于 2740 天前的主题,其中的信息可能已经有所发展或是发生改变。

    是我笨蛋了吗, 计算天数是不是用 “时间戳 / (60 秒 * 60 分 * 24 小时)” (单位是秒)

    先请问是我这公式不对吗,如果对,可我计算出来会有问题,如:

    2017.6.1 07:00 与 2017.6.1 09:00 所得结果会多出 1 天,什么原因

    why,why,why

    28 条回复    2017-06-22 17:39:41 +08:00
    Perry
        1
    Perry  
       2017-06-22 02:56:14 +08:00
    为啥不把数据列出来
    SharkIng
        2
    SharkIng  
       2017-06-22 03:17:54 +08:00 via iPhone
    确定时间戳是以秒计数的么?
    cxbig
        3
    cxbig  
       2017-06-22 03:34:21 +08:00
    系统环境和配置未知,用什么语言未知,用什么日期库或运算方法未知。
    不知道怎么帮你。
    lzdhlsc
        4
    lzdhlsc  
       2017-06-22 03:36:03 +08:00
    2017.6.1 07:00 CST = 2017.5.31 23:00 UTC
    2017.6.1 09:00 CST = 2017.6.1 01:00 UTC
    时间戳一般是以 1970.01.01 00:00 UTC 为基准的,记录的是从基准时间过了多少秒(毫秒).
    TtiGeR
        5
    TtiGeR  
       2017-06-22 07:46:41 +08:00 via iPhone
    没考虑时区吧
    xyjtou
        6
    xyjtou  
       2017-06-22 07:56:08 +08:00 via Android
    一般语言时间计算都有标准库吧,不用手工造轮
    wl879
        7
    wl879  
    OP
       2017-06-22 08:00:18 +08:00
    其实用什么语言无关,我原本用 swift (是秒为单位),为方便我用 javascript 列一下

    var time1 = new Date("2017-6-1 7:00:00");
    var time2 = new Date("2017-6-1 9:00:00");

    console.log(time1, time1.getTime() / (60*60*24*1000))

    // 输出:Thu Jun 01 2017 07:00:00 GMT+0800 (CST) 17317.958333333332

    console.log(time2, time2.getTime() / (60*60*24*1000))

    // 输出:Thu Jun 01 2017 09:00:00 GMT+0800 (CST) 17318.041666666668

    在补充一点,其实分割点是 8:00, 大于等于 8:00 就多了一天
    wl879
        8
    wl879  
    OP
       2017-06-22 08:07:37 +08:00
    @lzdhlsc @TtiGeR 请问,时间戳是 1970.01.01 00:00 UTC 过了多少秒,然后用秒数去计算过了多少天,而不是计算具体的日期,应该与时区无关吧,请揪正一下错误,网上看了很多博客文章是教如何计算的,可测过以后,都是错的,多耽误人啊
    Pitttttt
        9
    Pitttttt  
       2017-06-22 08:14:36 +08:00 via Android
    @wl879 GMT+800 都告诉你了时区啦,基准为 12 点我们这就是 8 点,当然在你看来就是已 8 点为分界线的啊
    0ZXYDDu796nVCFxq
        10
    0ZXYDDu796nVCFxq  
       2017-06-22 08:15:04 +08:00
    timestamp 是无时区的
    你在转换时没有把时区考虑进去
    7 点和 9 点,如果你的时区是东八区,换成 GMT 在日期上刚好相差 1 天
    wl879
        11
    wl879  
    OP
       2017-06-22 08:29:20 +08:00
    @Pitttttt @gstqc 没太懂,如果 timestamp 是无时区的, 我需求计算的是 过了多少天数, 而不是几月几号,与时区还有关吗,求一下具体的计算方法
    Rice
        12
    Rice  
       2017-06-22 08:36:54 +08:00
    计算结果不是 2 小时吗??
    Rice
        13
    Rice  
       2017-06-22 08:37:21 +08:00
    @Rice #12 哦哦,我看错了
    0ZXYDDu796nVCFxq
        14
    0ZXYDDu796nVCFxq  
       2017-06-22 08:40:39 +08:00 via iPhone
    @wl879 因为你用你本地的时间就带时区了。
    比如中国的 22 号早上 7 点,在 GMT 的时区那还是 21 号 23 点,日期就相差 1 了啊
    XYxe
        15
    XYxe  
       2017-06-22 08:41:29 +08:00
    你用 (time2.getTime() - time1.getTime()) / (60*60*24*1000) 得到的就是你想要的结果了。
    先转成天数就用的是 UTC 时间的天数了。
    Pitttttt
        16
    Pitttttt  
       2017-06-22 08:41:44 +08:00 via Android
    @wl879 算出来的没时区,但是你现在是+8 就是东 8 区,他会再算到你现在在的时区,就是要+8
    0ZXYDDu796nVCFxq
        17
    0ZXYDDu796nVCFxq  
       2017-06-22 08:43:41 +08:00 via iPhone
    再说楼主的需求
    只是算个天数,直接 日期减去 1970-01-01 就行了啊
    在时区和无时区之间换算多麻烦
    Rice
        18
    Rice  
       2017-06-22 08:43:42 +08:00
    难道不是换算成 GMT 刚好是 23 点和 1 点,正好过一天?
    Rice
        19
    Rice  
       2017-06-22 08:44:23 +08:00
    Rice
        20
    Rice  
       2017-06-22 08:53:10 +08:00

    这样就好了
    Rice
        21
    Rice  
       2017-06-22 08:56:29 +08:00
    @Rice #20 操,时区……算了
    nirocfz
        22
    nirocfz  
       2017-06-22 09:04:17 +08:00   ❤️ 1
    这好像不是个关于时间,更不关于时区的问题

    不提这样算天数差值好不好。

    光看 那个结果,没多出一天啊,17318.041666666668 - 17317.958333333332 怎么大于 1 了,明明是 0.08333333333575865 (天)

    0.08333333333575865 * 60 * 60 * 24 = 7200。7200 秒,两小时,7 点到 9 点
    oicebot
        23
    oicebot  
       2017-06-22 09:05:32 +08:00
    是我没睡醒,还是楼主的问题描述有歧义?

    到底是问“这两个时间戳的日期差值” 还是“这两个时间戳之间差了多少天”?

    如果说是两个时间戳的日期差值,那才是分别把秒换算成 UTC 日期,然后日期相减得出差值……

    如果说差了多少天,那肯定是先相减算出差了多少秒,再把秒换算成天(时间长度单位)吧?
    lifanxi
        24
    lifanxi  
       2017-06-22 09:07:10 +08:00   ❤️ 1
    你那个算法里面假设了太多的东西,表面上看就是个时区的问题,实际上还有别的问题。要简单一点归避掉时区的问题的话,你可以先做减法再做除法。

    然而,我想说的时,任何有关时间的计算,请使用标准库的数据结构与实现,避免依赖本地时间进行计算。自己土法实现的(比如除以 24,除以 60,除以 365 等等),99%都在某种场景下是错的。

    因为有关时间,你不但要考虑一般的时区、闰年这种特性,还有考虑闰秒、夏时制、非整数时区等这些稍微有点特殊的场景,还得考虑其它本地时间不连续等更为复杂的场景。这也就是为什么 Linux 系统里有个需要不定期更新的 tzdata 包的原因。
    infong
        25
    infong  
       2017-06-22 09:54:38 +08:00
    楼主的问题出在这里:
    var time1 = new Date("2017-6-1 7:00:00");
    var time2 = new Date("2017-6-1 9:00:00");

    这里定义的时间是有时区的,通过 time1.toString() 能看到时间是 "Thu Jun 01 2017 07:00:00 GMT+0800 (CST)"
    所以 time1 所对应的时间戳为 "Thu May 31 2017 23:00:00 GMT" 的时间戳

    猜猜下面输出是什么?
    var time3 = new Date('1970-1-1 00:00:00');
    console.log(time3/86400);
    amlun
        26
    amlun  
       2017-06-22 10:48:15 +08:00
    talk is cheap,show me the code!
    dinghua
        27
    dinghua  
       2017-06-22 11:37:12 +08:00
    我来解释解释;

    楼主看到结果一个是 17317.x , 一个是 17318.x, 就认为是两个时间不是在同 1 天。

    至于为什么,大家都提了,时区的问题。
    hicdn
        28
    hicdn  
       2017-06-22 17:39:41 +08:00
    @wl879

    var time1 = new Date("2017-6-1 7:00:00");
    var time2 = new Date("2017-6-1 9:00:00");

    console.log(time1, time1.getTime() / (60*60*24*1000))

    // 输出:Thu Jun 01 2017 07:00:00 GMT+0800 (CST) 17317.958333333332

    console.log(time2, time2.getTime() / (60*60*24*1000))

    // 输出:Thu Jun 01 2017 09:00:00 GMT+0800 (CST) 17318.041666666668

    你这个都是按照浏览器的 +8 时区 输出的本地时间,然而时间戳是按 0 时区算的。
    转换成 0 时区
    time1 2017.05.31 23:00 GMT+0000
    time2 2017.06.01 01:00 GMT+0000
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:24 · PVG 21:24 · LAX 05:24 · JFK 08:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.