coderstory
V2EX  ›  Java

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

  •  
  •   coderstory ·
    coderstory · Dec 11, 2023 · 8076 views
    This topic created in 1022 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

    spring 内置的国际化 LocaleContextResolver,基于它统一转换出入参
    wokerrrrrrrrr
        20
    wokerrrrrrrrr  
       Dec 13, 2023
    我的实践是这样的:
    1.后端 java 代码统一使用 java8 的 Instant 时间类
    2.数据库 mysql 统一用 bigint 存储时间戳
    然后剩下的就是各种转换的事儿了,根据前端需要,既可以返回时间戳,也可以返回带时区的时间格式字符串( ISO 标准那种)。
    前端具体展示什么时区,从返回数据里再转就行了
    wokerrrrrrrrr
        21
    wokerrrrrrrrr  
       Dec 13, 2023
    @wokerrrrrrrrr 前后端传参约定好用 ISO 标准的时间字符串或者时间戳,时区就错不了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1120 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 17:37 · PVG 01:37 · LAX 10:37 · JFK 13:37
    ♥ Do have faith in what you're doing.