XMLGregorianCalendar转java.time.Instant并切换时区问题排查
问题分析与解决方案
我来帮你拆解下问题根源,再给出靠谱的解决办法:
问题出在哪?
你的XMLGregorianCalendar实例xgc的值是2018-04-13T06:30:23,这个字符串没有携带时区偏移或时区ID信息。当你调用xgc.toGregorianCalendar()时,这个方法默认会用JVM当前的默认时区来构建GregorianCalendar,而不是你预期的America/Chicago时区。这就导致后续转换出的Instant不是基于芝加哥时间计算的UTC时间,结果自然不符合预期。
正确的转换方式
我们需要显式指定America/Chicago时区,把XMLGregorianCalendar的本地时间关联到该时区,再转换为UTC的Instant。这里提供两种可靠的实现方式:
方式一:用java.time API(推荐,Java 8+)
新的日期API逻辑更清晰,步骤如下:
XMLGregorianCalendar xgc = header.getCaptureDate(); // 指定美国中部时区 ZoneId chicagoZone = ZoneId.of("America/Chicago"); // 将XMLGregorianCalendar的时间字段转为无时区的LocalDateTime LocalDateTime localDateTime = LocalDateTime.of( xgc.getYear(), xgc.getMonth(), xgc.getDay(), xgc.getHour(), xgc.getMinute(), xgc.getSecond() ); // 关联到芝加哥时区,得到带时区的时间对象 ZonedDateTime chicagoDateTime = ZonedDateTime.of(localDateTime, chicagoZone); // 转换为UTC的Instant Instant convertedDateTime = chicagoDateTime.toInstant();
方式二:用GregorianCalendar的重载方法
如果你更习惯旧的日期API,可以直接用重载方法指定时区:
XMLGregorianCalendar xgc = header.getCaptureDate(); // 显式传入芝加哥时区构建GregorianCalendar GregorianCalendar gc = xgc.toGregorianCalendar( TimeZone.getTimeZone("America/Chicago"), Locale.getDefault(), null ); // 转换为UTC的Instant Instant convertedDateTime = gc.toInstant();
验证结果
2018年4月13日美国中部处于夏令时(CDT,UTC-5),所以芝加哥时间2018-04-13T06:30:23对应的UTC时间是2018-04-13T11:30:23Z,转换后的Instant应该是这个值,你可以打印出来验证。
内容的提问来源于stack exchange,提问作者Antona
相关产品推荐
相关产品推荐

