web 开发涉及到时间的是一律使用 utc 时间吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
myyou
V2EX    Python

web 开发涉及到时间的是一律使用 utc 时间吗?

  •  1
     
  •   myyou 2016-07-21 15:26:34 +08:00 8941 次点击
    这是一个创建于 3379 天前的主题,其中的信息可能已经有所发展或是发生改变。
    第 1 条附言    2016-07-21 17:38:31 +08:00
    评论下有人建议使用 unix 时间戳,但是 unix 时间日期是 1970~2038 ,不再这个范围的不是会出现问题?
    61 条回复    2016-07-23 11:42:06 +08:00
    julyclyde
        1
    julyclyde  
       2016-07-21 16:31:35 +08:00
    保存的时候应该用 UTC ,但似乎很少有遵守的
    展现的时候当然要本地化了
    haozhang
        2
    haozhang  
       2016-07-21 16:34:04 +08:00 via iPhone
    保存全部使用 utc 我觉得的是最佳方案,取值转换成 local time 即可
    cevincheung
        3
    cevincheung  
       2016-07-21 16:43:03 +08:00
    为什么就不能存时间戳。
    myyou
        4
    myyou  
    OP
       2016-07-21 17:05:35 +08:00
    @julyclyde
    @haozhang
    如果存储字符呢,例如: 2016-07-21 这样的格式,也要存成 utc 吗?
    pubby
        5
    pubby  
       2016-07-21 17:07:16 +08:00 via Android
    一律使用同一个时区,所有机器 NTP 对时,时区设置相同即可
    skydiver
        6
    skydiver  
       2016-07-21 17:08:40 +08:00
    一律使用 unix 时间戳
    myyou
        7
    myyou  
    OP
       2016-07-21 17:20:59 +08:00
    @skydiver 一般不存 datetime 之类的时间吗?
    imnpc
        8
    imnpc  
       2016-07-21 17:23:05 +08:00
    只建议用 unix 时间戳...
    myyou
        9
    myyou  
    OP
       2016-07-21 17:28:11 +08:00
    @imnpc 如果涉及到个人生日呢?
    myyou
        10
    myyou  
    OP
       2016-07-21 17:30:14 +08:00
    @cevincheung 如果涉及到个人生日呢?
    imnpc
        11
    imnpc  
       2016-07-21 17:31:25 +08:00
    @myyou
    个人生日那些随便存啊
    一般按照简单的 datatime 就可以或者纯文本

    时间戳使用在各种计算比较上的 比较方便
    myyou
        12
    myyou  
    OP
       2016-07-21 17:35:00 +08:00
    @cevincheung
    @imnpc
    @skydiver
    还有 unix 时间戳截止日期不是 2038 年吗?
    cevincheung
        13
    cevincheung  
       2016-07-21 17:37:26 +08:00
    @myyou
    date --date='@32472119461'

    看看输出啥。 233333
    myyou
        14
    myyou  
    OP
       2016-07-21 17:40:17 +08:00
    @cevincheung 64 位 ubuntu 14.04 输出这个: Tue Jan 1 01:11:01 CST 2999
    cevincheung
        15
    cevincheung  
       2016-07-21 17:45:43 +08:00
    @myyou 对啊。
    haozhang
        16
    haozhang  
       2016-07-21 18:05:16 +08:00 via iPhone
    @myyou 这肯定不对啊,日期不是同一天的时区怎么办?
    loading
        17
    loading  
       2016-07-21 18:32:58 +08:00 via Android
    unix 时间是从 1970 年 01 月 01 日 0:00:00 起算,用的是 utc 时区,所以也可以理解是另一种 utc 时间。
    2038 年是 32 位长度带来的精度问题,这个问题不同于千年虫问题。千年虫是判断 2000 年是闰年,少了一个判断,是代码错误。
    64 位的 unix 时间够用了,而且现在大家其实都在用了。
    loading
        18
    loading  
       2016-07-21 18:36:15 +08:00 via Android
    @haozhang unix 时间用的是 utc 时间
    haozhang
        19
    haozhang  
       2016-07-21 18:50:23 +08:00
    @loading 我说的东西和 unix 用不用 utc 时间有什么关系...
    loading
        20
    loading  
       2016-07-21 19:22:10 +08:00 via Android
    @haozhang 你不是说时区吗? utc 与格林威治时间 gmt 可以几乎认为相等。
    allenhu
        21
    allenhu  
       2016-07-21 19:23:55 +08:00 via Android   1
    搞清楚你的应用几国人在用,生命周期是多久,就清楚了
    haozhang
        22
    haozhang  
       2016-07-21 19:49:12 +08:00 via iPhone
    @loading 我说的是日期错位啊...
    caixiexin
        23
    caixiexin  
       2016-07-21 19:59:05 +08:00 via Android
    小于 1970 年的 Unix 时间戳,不是负数吗
    kookxiang
        24
    kookxiang  
       2016-07-21 20:02:48 +08:00
    unix 时间戳是到 2038 年?那只是因为你用 32 位的 int 来存而已吧
    x8
        25
    x8  
       2016-07-21 20:08:12 +08:00
    64 位的机器会有这个问题吗?
    skydiver
        26
    skydiver  
       2016-07-21 21:39:51 +08:00 via iPad
    @loading 千年虫不是闰年问题,是年份只用了两位整数来存的问题
    skydiver
        27
    skydiver  
       2016-07-21 21:40:15 +08:00 via iPad
    @myyou 用 64 位来存就没有 2038 问题了
    onlyice
        28
    onlyice  
       2016-07-21 22:03:37 +08:00
    expkzb
        29
    expkzb  
       2016-07-21 22:10:21 +08:00
    时间戳的问题在于不能表示时区,遇到航班信息就傻眼了
    loading
        30
    loading  
       2016-07-22 06:17:05 +08:00 via Android
    @skydiver 其实就是闰年问题。
    loading
        31
    loading  
       2016-07-22 06:18:41 +08:00 via Android
    @skydiver 哦,闰年问题是带来的主要问题之一…特别明显。
    tausi0661
        32
    tausi0661  
       2016-07-22 08:34:21 +08:00
    是不是 utc/unix 无所谓, 只要存储的所有时间是统一的时区就好, 并保证各 server 的时区及时间一致.
    lifanxi
        33
    lifanxi  
       2016-07-22 08:53:40 +08:00
    @loading
    重复一下 26 楼的话:千年虫不是闰年问题,是年份只用了两位整数来存的问题。参考老版的 13 位身份证号码来理解。

    2000 年是闰年,而 1900 年不是,如果把 2000 年误作 1900 年,确实会造成 2 月少一天的问题。但这不是通常“千年虫”讨论的范畴,也不是像你说的那样,因为“千年虫是判断 2000 年是闰年,少了一个判断”, 2000 年是闰年没有问题,你说的“少了一个判断”(能否整除 400 )只会造成把 1900 年也判成闰年。
    mengzhuo
        34
    mengzhuo  
       2016-07-22 09:05:43 +08:00 via iPhone

    等你们公司开始做国际化的时候 后面的程序员会感谢你的
    xuboying
        35
    xuboying  
       2016-07-22 09:09:12 +08:00 via Android
    @expkzb 航班时间这种涉及跨时区的不用时间戳才傻了。记录了时间戳用户才能得到不同时区的时间正确表示,特别是还有地方有夏时制冬时制,每次显示都要换算正确
    lifanxi
        36
    lifanxi  
       2016-07-22 09:18:03 +08:00
    时间其实是个很复杂的东西,但是可以把它理解成是个自然流逝的东西,然后人为给每一秒(毫秒也行,单位不重要,取决于你需要精度)进行计数。

    这个计数值在计算机领域通常可以用 Unix 时间戳来表示,在不考虑实现(变量位数)的前提下,这个计数值可以表示任意时间范围。所谓只能表示 1970-2038 是因为假设了只用有符号 32 位整型数的非负数部分对秒计数的原因。

    所以,用一个足够长的有符号整数来表示任意时间是没有问题的。但这个数值本身并不具有“时区”的含义,时区只在把它转换为人类可读的表示方式时才要考虑的问题。

    这个转换工作应该 100%交给操作系统去实现,而不应该自己土法按一年 365/366 年、每天 24 小时、每小时 60 分钟、每分钟 60 秒再加上时间偏移去计算,甚至前一天、后一天这种计算也应该用系统库去完成,而不要自己去做。

    因为时间日期计算里有太多坑了,基本上 99.9%的程序员自己实现的版本不会比系统已有的版本要好。最简单的有闰年、复杂一点的时区和夏时制、再复杂一点有闰秒、更复杂一点是一些历史特殊情况(比如时区变更)。
    yaodong
        37
    yaodong  
       2016-07-22 09:21:56 +08:00
    http://yellerapp.com/posts/2015-01-12-the-worst-server-setup-you-can-make.html


    > TL;DR Use UTC as the only timezone for your servers.
    BlueMeow
        38
    BlueMeow  
       2016-07-22 10:20:05 +08:00
    @lifanxi 对。有时候由于临时增加的闰秒、地区时区调整、夏令时等问题,时间存在处理各种陷阱。比如 http://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result 这个问题就是因为 1927 年上海时区调整引起的,这种细节自己处理的话总会有疏漏。
    bingwenshi
        39
    bingwenshi  
       2016-07-22 11:42:29 +08:00
    做个编程习惯良好的工程师,把时间都存储成 UTC 时间, 只是在展示的时候,根据用户时区再做转换就行了
    julyclyde
        40
    julyclyde  
       2016-07-22 11:58:03 +08:00
    使用 UTC 可以保证时序
    不要忘了所谓弟弟比哥哥先出生的夏令时事故
    julyclyde
        41
    julyclyde  
       2016-07-22 11:58:42 +08:00
    @loading 千年虫是年份只保留两位,不支持 21 世纪;而不是 2000 闰年的问题
    julyclyde
        42
    julyclyde  
       2016-07-22 11:59:03 +08:00
    @loading GMT 没有全球广泛的法律效力,虽然和 UTC 数值基本一致
    julyclyde
        43
    julyclyde  
       2016-07-22 12:00:36 +08:00
    另外 China standard time 据说不支持闰秒,在闰秒时会两次出现 59 秒,有可能发生逆序事故; UTC 是支持的
    loading
        44
    loading  
       2016-07-22 12:04:13 +08:00 via Android
    @julyclyde 嗯,你掌握得很全面。
    expkzb
        45
    expkzb  
       2016-07-22 12:34:56 +08:00
    @xuboying 请看你楼下的回复
    xuboying
        46
    xuboying  
       2016-07-22 13:12:39 +08:00 via Android
    @expkzb 是啊,下面也是表示要用 epoch 。时间戳表示了一个确定的时刻, human 时间只是加上时区 /dst 的时间戳不同表现显示而已
    silver107
        47
    silver107  
       2016-07-22 13:29:48 +08:00
    存时间戳,是不是没有时区问题
    rubyvector
        48
    rubyvector  
       2016-07-22 14:00:25 +08:00
    最近也遇到此问题.如果用户是跨时区的,可得注意了.不然大乱
    Comdex
        49
    Comdex  
       2016-07-22 14:28:16 +08:00
    @rubyvector
    @julyclyde
    @bingwenshi
    @lizon
    @skydiver 请教一下各位,在数据库中保存时间是使用 datetime 或字符串还是使用 int64 类型保存时间截好?现在比较普遍的做法是怎样的?
    quix
        50
    quix  
       2016-07-22 14:49:49 +08:00
    @myyou 生日的话... 并不是时间 只是个几月几日的信息, 连年份都没有
    如果说的是出生日期( dob) 的话则是一个不含时区的日期 因此也不应该是作为时间戳保存而应该作为字符串保存 ( 如果需要查询时进行比较可以存成统一时区的日期, 最好是 utc )
    Mirana
        51
    Mirana  
       2016-07-22 14:51:29 +08:00
    存时间戳也有时间问题啊 主要是是时区的问题
    jybox
        52
    jybox  
       2016-07-22 14:52:05 +08:00
    首先内部表示和物理层面肯定是存 UTC ,几乎所有数据库都是这样的(他们接受任何时区的时间,但会存成 UTC )。但如果你存 UTC 的话,一定要把时区也一起存起来(可能要放到单独的字段,要看数据库支持不支持)。

    因为时区是一个有关时间的重要元信息(和时区相关联的不仅仅是偏移量,还包括夏令时和冬令时之类的东西),当然不应该丢掉它。否则例如一个人在中国发了一个帖子,又去美国发了一个帖子,那么如果服务器不存时区,只依赖客户端时区的话,就可能会发现两个帖子是同一时间,甚至后一个帖子的时间比前一个更早。

    至于客户端和服务器端之间的 API ,我认为双方都要有接受任何时区的时间的能力,现在绝大部分的语言都提供了这样的能力。发送的时候,客户端按照本地时区发送(以便把时区这个信息传递给服务器);服务器在发送时,则以数据库中记录的,客户端的时区来发送。
    cxbig
        54
    cxbig  
       2016-07-22 15:40:43 +08:00
    我司服务器时间和存数据库的各种时间一律用 UTC ,前端根据实际业务时区做转换输出输入。
    mgcnrx11
        55
    mgcnrx11  
       2016-07-22 17:17:08 +08:00
    @julyclyde 请教一下,看了一下 wiki 上 UTC 的介绍, UTC 是会在适当的时候增加闰秒来保持与 GMT 不差超过 1 秒的。那么,对于要做日期转换的工具库(类)来说,岂不是需要针对未来未知的某个闰秒做更新,才能正确转换时间?否则闰秒会造成转换的时候多了一秒这种情况吧?
    dorentus
        56
    dorentus  
       2016-07-22 18:46:53 +08:00 via iPhone
    你的操作系统底层都是用 unix epoch 或者类似 unix epoch 的方式表达时间的。
    owt5008137
        57
    owt5008137  
       2016-07-22 19:08:25 +08:00 via Android
    @myyou 现在 unix 时间戳基本上都用 int64 保存了,除非你强制往 int32 转。所以反正你活着的时候肯定够用了
    janxin
        58
    janxin  
       2016-07-22 20:01:23 +08:00
    UNIX 时间戳用 int64 ,够用了啊
    julyclyde
        59
    julyclyde  
       2016-07-22 22:56:23 +08:00
    @mgcnrx11 首先你要知道 UTC 是根本,闰秒是在 UTC 里做的;到各个行政时区,是 59 秒之后 60 秒,还是 59 秒之后又一个 59 秒,或者做夏令时处理,那是各国政府自己的事了。保存、传输都用 UTC ,直到最后展现的时候才用行政时区,可以做到损失的最小化
    julyclyde
        60
    julyclyde  
       2016-07-22 23:05:44 +08:00
    https://access.redhat.com/articles/1187353
    http://www.cnbeta.com/articles/437413.htm
    https://mm.icann.org/pipermail/tz-announce/2015-August/000033.html
    Changes affecting future time stamps

    North Korea switches to +0830 on 2015-08-15. (Thanks to Steffen Thorsen.)
    The abbreviation remains "KST".
    banxi1988
        61
    banxi1988  
       2016-07-23 11:42:06 +08:00
    首先,支持 UTC, 但是主要的是要统一啊,
    印象中,以前 LeanCloud 是 +8 时间,后来改成统一 UTC 时间了.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1134 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 17:49 PVG 01:49 LAX 10:49 JFK 13:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86