Home  >  Article  >  Java  >  How does SpringBoot dynamically display time based on the user's system time zone?

How does SpringBoot dynamically display time based on the user's system time zone?

WBOY
WBOYforward
2023-05-17 08:10:051769browse

Dynamic display of time based on user system time zone

When we use SpringBoot Mysql to develop the system, we always set the UTC 8 time zone uniformly, so that when users access the system in any region, the time displayed is the domestic standard time. The experience is not user-friendly. Let’s get the time zone of the current user’s system to show different times to the user.

1. Obtaining the user time zone

We can obtain the time zone of the system through JavaScript, and then set it uniformly in the request header.

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

2. Core code

LocalDateTime is used uniformly here to more conveniently handle time zone conversion issues by identifying the time zone to which the current LocalDateTime object belongs and then converting it to the target time zone time.

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

3. SpringBoot uniformly processes the time zone when returning json

When the program reads from the database and converts it into a LocalDateTime object, and processes it with business logic, the object still belongs to UTC 8. Time zone, the corresponding ZoneId=Asia/Shanghai, when it needs to be returned to the front end, you can use a custom jackson serializer to convert the LocalDateTime to the user's target time zone before converting it to 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
	{
		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
	{
		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())));
		};
	}
}

The above example code sets the user time zone ZoneId=Africa/Sao_Tome, and customizes the LocalDateTime deserializer. When using the ResquestBody annotation, the LocalDateTime attribute value in the object will also be converted to UTC 8 time zone , no additional processing is required and can be saved directly to the database.

4. SpringBoot receives time parameters and processes time zones uniformly

In addition to receiving parameters through the ResquestBody annotation as mentioned above, it is also possible to receive LocalDateTime objects through Get or Post parameters. At this time we need to Customize a Converter to handle the conversion of String to LocalDateTime, and at the same time convert the objects submitted by the user that belong to the user's time zone into UTC 8 time zone objects.

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer
{
	@Autowired
	private WebMvcProperties webMvcProperties;	@Override
	public void addFormatters(FormatterRegistry registry)
	{
		registry.addConverter(new Converter()
		{			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"));
			}		});
	}}

The above is the detailed content of How does SpringBoot dynamically display time based on the user's system time zone?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete