首頁  >  文章  >  Java  >  SpringBoot怎麼根據使用者係統時區動態展示時間

SpringBoot怎麼根據使用者係統時區動態展示時間

WBOY
WBOY轉載
2023-05-17 08:10:051868瀏覽

根據使用者係統時區動態展示時間

當我們使用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"));
			}		});
	}}

以上是SpringBoot怎麼根據使用者係統時區動態展示時間的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除