关于软件开发中的跨地区的时区问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
kushu001
V2EX    程序员

关于软件开发中的跨地区的时区问题

  •  
  •   kushu001
    NeegixOpensourceGroup 316 天前 3699 次点击
    这是一个创建于 316 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在最近的开发过程中,发现数据库服务器的时间是比北京时间少 8 小时的,所以存数据的时候,时间字段自动扣减了 8 小时。

    因为这个现象,我突然想到跨时区的应用在处理这样的时间问题,一般都是怎么处理的,有点不太理解
    目前看到的一个方案是,数据库和应用服务器都处理标准时间,不同时区的客户端自行解析时间?

    但是我总感觉有点问题,特此在 v2 站点寻求一点处理方案,看看各位大佬,有没有好的解决办法
    45 条回复    2024-12-01 00:47:57 +08:00
    2han9wen71an
        1
    2han9wen71an  
       316 天前
    时间戳
    ashong
        2
    ashong  
       316 天前 via iPhone
    存 utc
    Plutooo
        3
    Plutooo  
       316 天前   2
    你看到的方案没问题,服务端只返回时间戳给客户端,客户端根据用户时区自行解析
    ivvei
        4
    ivvei  
       316 天前
    你感觉有点问题,什么问题?
    lbunderway
        5
    lbunderway  
       316 天前
    utc
    cowcomic
        6
    cowcomic  
       316 天前   4
    要是就是针对一个时区内的开发,那就全部统一成这个时区,比如就开发国内的东西,那就都用东八区
    要是开发一个系统涉及多时区共用,那就是后台统一成标准时间 UTC ,然后前端再去自行改变,可以通过定位或者子域名或者目录层级都可以。
    要是系统庞大涉及跨区域独立部署,那中央机房保持 UTC ,其他各时区独立部署的可以设置对应时区,再在数据同步时进行归一
    kushu001
        7
    kushu001  
    OP
       316 天前
    @ivvei 只是感觉,说不上来,如果后续要进行数据分析,是不是会比较困难?我看数据库里存 timestamp 好像也没有时区的显示啊,是要另外做一个字段显示?
    nzynzynzy
        8
    nzynzynzy  
       316 天前   2
    数据处理储存一定用 UTC ,不要搞这种减八小时。很多地方都有夏令时冬令时的切换,这个时差可能随时+1 / -1
    barrywey
        9
    barrywey  
       316 天前
    服务端的程序,以及数据存储,永远都使用 UTC ,已 UTC 为基准。

    应用(浏览器、客户端等)请求数据的时候,根据所处的地区自己转换为本地时间。

    应用和服务端之间传输数据的过程,还是已 UTC 为准。
    ksedz
        10
    ksedz  
       316 天前
    时间戳或者 UTC ,需要注意的是有些 orm (不仅仅是数据库)会自动根据时区进行转换,需要处理下。
    zeromake
        11
    zeromake  
       316 天前 via Android
    @barrywey 然后一往 db 里塞了发现 db 有自己的时区()
    esee
        12
    esee  
       316 天前
    都是存储和返回时间戳给客户端自己解析的。。纯数字的时间戳才方便做各种分析
    barrywey
        13
    barrywey  
       316 天前
    @zeromake 数据库也要 UTC ,或者干脆整个服务器都配置成 UTC
    rocmax
        14
    rocmax  
       316 天前 via Android
    timestamp 是绝对的,日期和本地时间是相对的。如果服务器和客户端无法强制统一时区,则系统测一律使用 utc ,客户端按照本地时区转换。
    浏览器提供了本地时区检测 api ,
    vczyh
        15
    vczyh  
       316 天前
    数据库怎么存和服务保持一致就行,服务返回给渲染层按照 ISO8601 https://en.wikipedia.org/wiki/ISO_8601 来,这个我觉得比时间戳直观。
    rocmax
        16
    rocmax  
       316 天前 via Android
    @rocmax 同时也应该提供手动切换选项。
    前一阵用 nextjs 开发 app ,服务端渲染时时区更是个麻烦事,需要客户端将时区存在 cookie 里,服务端根据客户请求渲染页面。
    Mithril
        17
    Mithril  
       316 天前
    存储不要用 UTC ,用 DatetimeOffset ,主要是相比 UTC ,它有个时区的偏移量。
    这样你能知道你这条数据,是从哪个时区生成的。特别是你在同一个服务器中处理不同时区发过来的数据时,未来你如果想要显示这数据生成时的本地时间,那你存 offset 会省很多事。你如果只存 UTC ,等你加了这需求的时候会有大把的数据显示不正常。所以如果你做跨国的应用,不如从开始就存 offset 。
    然后所有程序中处理的时候都用它来做,最终显示的时候再转换回本地时区。
    zeromake
        18
    zeromake  
       316 天前 via Android
    @barrywey 然后联系运维,运维说是云的数据库,改起来太麻烦了……
    dode
        19
    dode  
       316 天前
    所有的中国服务器,软件,环境变量等配置好东八时区
    nekochyan
        20
    nekochyan  
       316 天前
    我们现在是直接服务器是 0 时区,直接 UTC 存储,然后再配置一个业务要跑在哪个时区字段偏移量,所有业务算时间用统一接口会加上这个偏移量去计算,客服端同理用服务器下发的偏移量计算;这样可以跑在任意时区,避免夏令时问题
    wangtian2020
        21
    wangtian2020  
       316 天前
    沙雕后端拉出来打一顿,正确的设计是数据库一律存时间戳,时间戳又没有时区的概念。HTTP 中的时间字段也一律传递时间戳,前端 dayjs 控制显示可太方便了
    charlie21
        22
    charlie21  
       316 天前
    server date
    数据库
    项目默认时间
    数据表条目,都 utc

    对于日期读取很频繁的数据,在数据表设置 date_id 和 utc_date_id 栏位,int unsigned 数字类型,用于记录当地日期和 utc 日期 (比如 20241231)
    masterclock
        23
    masterclock  
       316 天前
    搞时间的么,先看看 https://github.com/kdeldycke/awesome-falsehood?tab=readme-ov-file#dates-and-time
    基本上:
    1. 一律 UTC
    2. 人输入的时间未必对应、或仅对应一个时间点
    xuanbg
        24
    xuanbg  
       316 天前
    只要你使用统一的时区存储数据,那不同时区用户的时间问题就是一个纯前端问题
    shyangs
        25
    shyangs  
       316 天前
    一律 UTF-8, 一律 UTC.
    gzldc
        26
    gzldc  
       316 天前
    直接存时间戳 返前段时解析带上系统时区再显示
    csys
        27
    csys  
       316 天前
    取决于需不需要 i18n ,如果不需要 i18n ,那就应该把所有环境时间统一设定为+8
    如果需要 i18n ,那就所有环境时间统一设定为 utc
    hackroad
        28
    hackroad  
       316 天前
    一律 UTC 0
    br_wang
        29
    br_wang  
       316 天前
    数据唯一性。终端上数据按哪种规格显示,是终端的事。
    thetbw
        30
    thetbw  
       316 天前
    你操作系统配置好时区,包括服务器,开发中一般用时间戳都是自动转换,例如 jdbc 的时间戳转换为 Java 的 Date ,然后 format 到前端显示。我猜你就是操作系统时间戳没有配置,所以按照 UTC 标准时间来了
    dlam007
        31
    dlam007  
       316 天前
    做境外开发的回答下。
    可以了解下 i18n 和 icu ,还有 tzdate 这套。都有标准方案和工具的。

    存储侧:一般都是数据库存时间戳。
    传输侧:客户端当地时间,需要转换为时间戳,传递给后端。
    展示测:也就是客户端,需要获取用户的时区、region 信息(手机系统获取,用户 app 设置,经纬度之类的),然后转换成当地时间展示。
    Yanlongli
        32
    Yanlongli  
       316 天前
    首先,数据库有些类型是支持时区的,那就会按客户端选择的时区展示(不同时区返回不一样的时间值),客户端不指定时按服务配置的时区展示。对于不包含时区的类型,需要定一个固定且统一的时区,需要其它时区时根据固定时区进行加减。int 存储时一律按 UTC 存储,转换时可以指定时区,不要说不指定时区时(默认 UTC )显示的少 8 个小时,因为这个不是北京时间自然少,不要错把 UTC 时区时间当作北京时区时间。
    julyclyde
        33
    julyclyde  
       316 天前
    还有就是需要区分数字时区和地名时区,这俩可不是完全一致的
    涉及到夏令时等行政更改的问题
    2015 的时候朝鲜曾经改到 8.5 后来又改回 9
    Configuration
        34
    Configuration  
       316 天前
    数据库都是存 UTC

    timestamp without time zone
    standchan
        35
    standchan  
       316 天前
    存 utc ,用的时候再根据业务再处理。简单方便
    p1gd0g
        36
    p1gd0g  
       316 天前
    用时间戳,别用 +- 小时,小心算出负数
    viking602
        37
    viking602  
       316 天前
    时间戳就好了 前端自己处理这个问题
    fantasy0v0
        38
    fantasy0v0  
       316 天前
    我用的 pg 库直接存 timestamp ,代码处理也是用 OffsetDateTime 等支持时区的类来处理,返回给前端的时候也会带上时区信息,前端自己再根据时区转换并展示(有现成的库来处理)。
    0xD800
        39
    0xD800  
       316 天前 via Android
    我现在遇到比这个更麻烦的问题,应用服务器和 minio 服务器时间有差异导致生成不了 presignurl 等时间同步对了 又可以生成绩
    nivalxer
        40
    nivalxer  
       316 天前
    api 接口返回给前端的时间类型统一用时间戳,目前暂时是这么处理的。
    thinkershare
        41
    thinkershare  
       316 天前
    时间是时间,时区是时区.
    如果你的服务器不需要用户的时区信息,直接存储 UTC 时间好了。显示的时候客户端按照当前时区将 UTC 时间转换为本地时间。
    如果需要储存用户时区,就需要额外的关注了。
    layxy
        42
    layxy  
       316 天前
    @cowcomic 这种情况日常运维可能会有问题,比如数据库查询数据都是 utc,日志中打印的日期也是 utc,排查问题不是很方便
    pkoukk
        43
    pkoukk  
       316 天前
    时间戳最简单
    realpg
        44
    realpg  
    PRO
       315 天前
    一律存时间戳 uint32 或者 int64
    cowcomic
        45
    cowcomic  
       315 天前
    @layxy 只要标准是统一的,这些问题都能解决。如果真的是这种多区域分布式系统,体量就已经很大了,日志也不可能就这么去机器上查,肯定通过 ELK 收集起来再统一开放,到时候在查询层各自做转换也很方便。而且 DB 会有专门的 DB 团队维护,日志可以统一交给基础层团队去维护,整体的时间转化走统一组件。不可否认肯定要比独立小系统麻烦,但大体量带来的复杂性是无法避免的,这总比各自时间规范不一致带来的业务风险要强
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1005 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 18:41 PVG 02:41 LAX 11:41 JFK 14:41
    Do have faith in what you're doing.
    ubao 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