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

 更新时间:2023年01月06日 16:15:00   作者:RealJt  
这篇文章主要介绍了SpringBoot如何根据用户系统时区动态展示时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

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

当我们使用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负责获取用户时区,并且每次请求时带到后台,后台在接收请求和返回前端时统一转换用户时区,业务处理时不必再考虑时区问题。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java常见的字符串操作和日期操作汇总

    java常见的字符串操作和日期操作汇总

    本文主要对java 常见的字符串操作和日期操作进行整理。具有一定的参考价值,需要的朋友一起来看下吧
    2016-12-12
  • Pulsar负载均衡原理及优化方案详解

    Pulsar负载均衡原理及优化方案详解

    这篇文章主要为大家介绍了Pulsar负载均衡原理及优化方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • java微信扫码支付模式一线下支付功能实现

    java微信扫码支付模式一线下支付功能实现

    本篇文章主要介绍了JAVA微信扫码支付模式一线下支付功能实现,具有一定的参考价值,有需要的可以了解一下。
    2016-11-11
  • JAVA设计模式零基础解析之单例模式的八种方式

    JAVA设计模式零基础解析之单例模式的八种方式

    设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
    2021-10-10
  • 利用Java工具类Hutool实现验证码校验功能

    利用Java工具类Hutool实现验证码校验功能

    这篇文章主要介绍了利用Java工具类Hutool实现验证码校验功能,利用Hutool实现验证码校验,校验的Servlet与今天的第一篇是一样的,唯一就是验证码的生成是不一样的,利用Hutool生成验证码更快捷.需要的朋友可以参考下
    2022-10-10
  • Java操作excel的三种常见方法实例

    Java操作excel的三种常见方法实例

    这篇文章主要给大家介绍了关于Java操作excel的三种常见方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Spring通过<import>标签导入外部配置文件

    Spring通过<import>标签导入外部配置文件

    之前文章里我们讲到Spring加载Xml配置文件的细节,那么加载完了我们肯定要解析这个配置文件中定义的元素。这篇我们首先来分析下Spring是如何通过标签导入外部配置文件的。
    2021-06-06
  • Java单机环境实现定时任务技术

    Java单机环境实现定时任务技术

    这篇文章主要介绍了Java单机环境实现定时任务技术,文章内容介绍详细,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-04-04
  • SpringMVC拦截器实现单点登录

    SpringMVC拦截器实现单点登录

    这篇文章主要介绍了SpringMVC拦截器实现单点登录,简单介绍了springmvc拦截器,单点登录实现原理等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java并发编程中的Exchanger解析

    Java并发编程中的Exchanger解析

    这篇文章主要介绍了Java并发编程中的Exchanger解析,Exchanger用于线程间数据的交换,它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据,这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange()方法,需要的朋友可以参考下
    2023-11-11

最新评论