V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kushu001
V2EX  ›  程序员

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

  •  
  •   kushu001 · 2 天前 · 2263 次点击
    在最近的开发过程中,发现数据库服务器的时间是比北京时间少 8 小时的,所以存数据的时候,时间字段自动扣减了 8 小时。

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

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

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

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

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

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

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