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

Spring boot 2.x 项目如何兼容不同时区的客户?

  •  
  •   coderstory ·
    coderstory · 2023-12-11 17:37:00 +08:00 · 4497 次点击
    这是一个创建于 385 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前有个 spring boot 2.7.15 的项目,已经开发了很多的功能。突然来了一个需求,存在美国的客户,如果是美国的客户打开的页面,时间数据都需要转换成美国客户的当地时区对应的时间,客户插入的数据对于在中国的客户而言,需要转换成 CST 时区的时间。

    也就是一个系统兼容多个时区的客户,时间需要都需要基于客户的时区处理掉。

    目前主要涉及的场景挺多的,比如 mysql 的数据查询和查询,查询的话用户给的时间筛选条件都得处理,查询结果中的时间类型的值需要处理,java 代码中的 LocalDate.now()之类的时间创建操作也要处理。表单提交的时间值都需要处理。。。

    整理一下,大概有如下场景需要处理 1.各种接口请求参数 这个可以 AOP 拦截 全部处理掉 2.java 代码中的时间创建 3.数据库中的时间创建 比如使用了 insert values (now()) 这种函数 或者时间字段设置了默认值 4.数据库查询返回了时间值 5.调用外部接口返回的值中的时间 ....

    需求目前只是大致的分析了一点,不知道各位大佬是否经历过这样的需求?给一点点经验吧

    21 条回复    2023-12-13 13:52:49 +08:00
    crazyweeds
        1
    crazyweeds  
       2023-12-11 17:40:21 +08:00
    国际化项目,用时间戳吧。
    psx2019
        2
    psx2019  
       2023-12-11 17:40:30 +08:00
    永远只存绝对时间戳,时区什么的是前端需要考虑的问题.
    shengchen11
        3
    shengchen11  
       2023-12-11 17:41:18 +08:00
    都用时间戳,前端处理时区
    Kyle18Tang
        4
    Kyle18Tang  
       2023-12-11 18:13:15 +08:00
    如果代码中都是用的 LocalDateTime ,那么请求响应使用 ISO-8601 的时间格式。统一在序列化反序列化的时候转成数据库时区。
    ragnaroks
        5
    ragnaroks  
       2023-12-11 19:58:11 +08:00
    要个工期改成时间戳,前端格式化
    uselessVisitor
        6
    uselessVisitor  
       2023-12-11 20:03:28 +08:00
    中间加这种破坏性的需求就很烦啊,最方便的就是改成时间戳,刷数据一劳永逸。不然为了这个需求会引入很多屎山
    lsry
        7
    lsry  
       2023-12-11 21:31:16 +08:00
    数据库存带时区的时间,前端根据时区转换成对应时间就好
    yjxjn
        8
    yjxjn  
       2023-12-11 21:37:02 +08:00
    上面说的带时区其实不太好,最好的方法就是在数据库里改成时间戳,而且是 UTC+0 时区,前端根据 user 浏览器来转换时间。+8 还是+9 的。
    clf
        9
    clf  
       2023-12-11 21:38:10 +08:00
    原则上,数据统一时区,无论服务器部署在哪里,后端和数据库都采用统一的时区处理。前端展示的时候才做国际化。

    (所以最好用时间戳
    cslive
        10
    cslive  
       2023-12-11 21:45:01 +08:00 via Android
    时间戳,前端根据不同时区转换
    realkaiway
        11
    realkaiway  
       2023-12-11 21:50:52 +08:00
    后端就存 UTC+0 的格式,清晰且直白,2023-12-11T22:00:00.000+00:00,前端用 dayjs 等封装一个工具类,带时间的提交统一转 utc ,展示的话则根据客户端的时区转 local
    BBCCBB
        12
    BBCCBB  
       2023-12-11 21:55:04 +08:00
    时间全都存 utc0 时间/时间戳, 前端自己转.
    cnhongwei
        13
    cnhongwei  
       2023-12-11 22:14:06 +08:00
    已有数据没有?如果没有的话,系统不变,将默认时区设置为 UTC ,后端如果使用 LocalDateTime 之类的,都不用修改,其它的都是前端的事了。如果已有数据,能停机修改最简单,如果不能的话,怎么热更新就很麻烦了。
    zjyl1994
        14
    zjyl1994  
       2023-12-11 22:28:14 +08:00
    DB 里存时间戳,然后过滤数据的时候前端的条件也都处理成时间戳再发过来查。
    前端展示的时候按照 Local 时区格式化就好了
    OnlySeePost
        15
    OnlySeePost  
       2023-12-12 00:49:32 +08:00 via Android
    数据库里存俩个,一个时区,一个当地时间。不能直接用 utc 时间。原因:冬/夏令时转换。比如 cet 时区,冬天是 utc+1 ,夏天是 utc+2 ,你要是冬天存个 cet 时间 9 点,那么数据库里就是 8 点,到了夏天,时区转化一下,就成了 10 点。
    tramm
        16
    tramm  
       2023-12-12 08:18:27 +08:00
    1.时间戳
    2.Header 中加时区信息,springboot 接收,返回都处理下.
    vczyh
        17
    vczyh  
       2023-12-12 09:35:26 +08:00
    建议改造一下,应用和数据库不动,但是和客户端交换的时间必须使用时间戳或者 https://en.wikipedia.org/wiki/ISO_8601
    huangcjmail
        18
    huangcjmail  
       2023-12-12 09:42:16 +08:00
    @OnlySeePost #15 你说的这个问题不存在吧,美东时间就是存在冬令时夏令时转换的。至少 Java 使用工具类去转换的时候,我只用传一个时间戳进去,它自己能识别到的。不管冬令时夏令时都是正确的。
    ikas
        19
    ikas  
       2023-12-12 20:31:15 +08:00
    无非就是后台服务端,db 统一时区,出入参转换携带时区统一转换
    api 出入参一般要么是使用带时区的格式,utc 时间戳,要么是额外参数传递时区,比如 cookie,header,query 参数

    spring 内置的国际化 LocaleContextResolver,基于它统一转换出入参
    wokerrrrrrrrr
        20
    wokerrrrrrrrr  
       2023-12-13 13:50:48 +08:00
    我的实践是这样的:
    1.后端 java 代码统一使用 java8 的 Instant 时间类
    2.数据库 mysql 统一用 bigint 存储时间戳
    然后剩下的就是各种转换的事儿了,根据前端需要,既可以返回时间戳,也可以返回带时区的时间格式字符串( ISO 标准那种)。
    前端具体展示什么时区,从返回数据里再转就行了
    wokerrrrrrrrr
        21
    wokerrrrrrrrr  
       2023-12-13 13:52:49 +08:00
    @wokerrrrrrrrr 前后端传参约定好用 ISO 标准的时间字符串或者时间戳,时区就错不了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1183 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:12 · PVG 02:12 · LAX 10:12 · JFK 13:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.