SpringBoot如何根据用户系统时区动态展示时间

作者:RealJt 时间:2021-09-23 23:37:10 

根据用户系统时区动态展示时间

当我们使用SpringBoot+Mysql开发系统时,总是统一设置UTC+8时区,这样用户在任何地区访问系统,展示的时间都是国内标准时间,体验不友好,下面通过获取当前用户系统所在的时区,给用户展示不同的时间。

一、用户时区的获取

我们可以通过JavaScript来获取系统所在的时区,然后统一设置在请求头里。

Intl.DateTimeFormat().resolvedOptions().timeZone; // Asia/Shanghai

二、核心代码

这里统一使用LocalDateTime,更方便的处理时区转换问题,通过标识当前LocalDateTime对象所属时区,然后转换为目标时区时间。

public LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}

三、SpringBoot返回json时统一处理时区

当程序从数据库中读取出并转换成LocalDateTime对象,并经过业务逻辑处理,这时候该对象还是属于UTC+8时区,对应的ZoneId=Asia/Shanghai,当需要返回给前端时,可以通过自定义jackson序列化器,在LocalDateTime转json前转换到用户目标时区。

@Configuration
public class JacksonConfiguration
{
@Autowired
private JacksonProperties jacksonProperties;/**
* 时区转换
*
* @param localDateTime
* @param originZoneId
* @param targetZoneId
* @return
*/
public static LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}/**
* LocalDateTime序列化
*/
public static class CustomLocalDateTimeSerializer extends JsonSerializer<LocalDateTime>
{
private DateTimeFormatter formatter;public CustomLocalDateTimeSerializer(DateTimeFormatter formatter)
{
super();
this.formatter = formatter;
}@Override
public void serialize(LocalDateTime value, JsonGenerator generator, SerializerProvider provider)
throws IOException
{
generator.writeString(convertLocalDateTime(value, ZoneId.of("Asia/Shanghai"), ZoneId.of("Africa/Sao_Tome"))
.format(formatter));
}}/**
* LocalDateTime反序列化
*
*/
public static class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime>
{
private DateTimeFormatter formatter;public CustomLocalDateTimeDeserializer(DateTimeFormatter formatter)
{
super();
this.formatter = formatter;
}@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JacksonException
{
return convertLocalDateTime(LocalDateTime.parse(parser.getText(), formatter), ZoneId.of("Africa/Sao_Tome"),
ZoneId.of("Asia/Shanghai"));
}}@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer()
{
return builder ->
{
builder.serializerByType(LocalDateTime.class,
new CustomLocalDateTimeSerializer(DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat())));
builder.deserializerByType(LocalDateTime.class,
new CustomLocalDateTimeDeserializer(DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat())));
};
}
}

上面示例代码设定用户时区ZoneId=Africa/Sao_Tome,并且自定义处理了LocalDateTime反序列化器,当使用ResquestBody注解时,对象中的LocalDateTime属性值也会转换成UTC+8时区,不用再额外处理,可直接保存到数据库。

四、SpringBoot接收时间参数统一处理时区

除了上面所说通过ResquestBody注解来接收参数外,还可能通过Get或者Post参数来接收LocalDateTime对象,这时候我们就要自定义一个Converter来处理String转换到LocalDateTime,同时把用户提交的属于用户时区的对象转换成UTC+8时区对象。

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer
{
@Autowired
private WebMvcProperties webMvcProperties;@Override
public void addFormatters(FormatterRegistry registry)
{
registry.addConverter(new Converter<String, LocalDateTime>()
{private LocalDateTime convertLocalDateTime(LocalDateTime localDateTime, ZoneId originZoneId,
ZoneId targetZoneId)
{
return localDateTime.atZone(originZoneId).withZoneSameInstant(targetZoneId).toLocalDateTime();
}@Override
public LocalDateTime convert(String source)
{
return convertLocalDateTime(
LocalDateTime.parse(source,
DateTimeFormatter.ofPattern(webMvcProperties.getFormat().getDateTime())),
ZoneId.of("Africa/Sao_Tome"), ZoneId.of("Asia/Shanghai"));
}});
}}

五、总结

通过上面的处理,JavaScript负责获取用户时区,并且每次请求时带到后台,后台在接收请求和返回前端时统一转换用户时区,业务处理时不必再考虑时区问题。

来源:https://blog.csdn.net/juntian2008/article/details/123867977

标签:SpringBoot,用户系统,时区,展示时间
0
投稿

猜你喜欢

  • 教你用JAVA写文本编辑器(四)

    2023-10-18 18:30:16
  • 简单了解springboot的jar包部署步骤

    2021-07-02 14:22:48
  • Java的Struts框架中登陆功能的实现和表单处理器的使用

    2022-05-20 23:44:45
  • Java多线程和并发基础面试题(问答形式)

    2022-03-29 17:39:42
  • Java实现导出ZIP压缩包的方法

    2023-05-06 04:58:57
  • C#使用IComparer自定义List类实现排序的方法

    2021-06-28 04:28:09
  • C#实现按照指定长度在数字前补0方法小结

    2023-02-23 09:42:32
  • VMware虚拟机下hadoop1.x的安装方法

    2023-07-27 08:01:40
  • Sprint Boot 集成MongoDB的操作方法

    2022-11-13 07:10:37
  • java实现图书检索系统

    2023-08-18 20:08:50
  • spring缓存自定义resolver的方法

    2021-05-30 17:07:56
  • volatile与happens-before的关系与内存一致性错误

    2021-12-13 20:25:37
  • RocketMQ消息过滤与查询的实现

    2023-06-26 10:04:25
  • Eclipse的Debug调试技巧大全(总结)

    2023-11-25 06:14:06
  • Java利用cors实现跨域请求实例

    2023-02-24 14:57:35
  • java图形用户界面实现菜单功能

    2023-11-23 11:50:58
  • c#中CAD文件读取实例

    2023-07-23 19:37:59
  • Java开发中可以防止界面假死的刷新代码

    2023-11-23 22:23:41
  • 谈谈Java中自定义注解及使用场景

    2022-08-28 04:45:39
  • JAVA实现单例模式的四种方法和一些特点

    2023-11-02 05:38:20
  • asp之家 软件编程 m.aspxhome.com