当我们使用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();
}当程序从数据库中读取出并转换成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时区,不用再额外处理,可直接保存到数据库。
除了上面所说通过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"));
} });
}}以上就是SpringBoot怎么根据用户系统时区动态展示时间的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号