在巴西DST期间,日期解析例外



输入巴西DST时间段时,时钟是1小时的。2014年,DST始于19/10,因此时间19/10/2014 00:00:00成为19/10/2015在01:00:00。"不存在"之间的时期。

因此,当使用TimeZone America/Sao_paulo解析日期" 19/10/2014 00:45:00"时,它会引发一个解析例外:Java.text.Parseexception:parseexception:无与伦比的日期:无与伦比的日期:" 19/10/10/10/10/10/10/2014 00:45:00"。

String date = "19/10/2014 00:59:00";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
sdf.setLenient(false);
sdf.setTimeZone("America/Sao_Paulo");
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo"));
calendar.setTime(sdf.parse(date));

美国/sao_paulo时区据称支持DST更改。这个问题的预期解决方案是什么?当DST期间开始和结束时,我必须手动更改JVM时区?当前," FIX"将JVM时区更改为DST期开始时GMT-2。

注意:此问题起源于Spring开发的应用程序。示例日期是从字符串转换为java.util.calendar时引发了例外。在上面的示例代码中,我设置了宽敞的false,以便能够重现错误。

java.util.Calendar代表时间瞬间。这种瞬间必须存在。当局部时间值落入弹簧的DST间隙时,这些值在时间上没有代表。换句话说,巴西的正确配置时钟将永远不会在2014年10月19日显示00:45:00。因此例外。有关视觉表示,请参见DST标签Wiki。

由于您正在解析用户输入,因此建议将字符串解析为LocalDateTime而不是Calendar。对于Java 7,您可以从Joda Time获得此功能。对于Java 8,它内置在新的java.time软件包中。

将其作为LocalDateTime,就可以决定从那里去哪里。如果时间无效(落入弹簧前向过渡的差距)或模棱两可(由于倒下后的过渡),则可以检测到这些方案并确定如何在应用程序中处理它们。

<</p>

tl; dr

使用 java.Time 在Account DST Cutover时从00:45到01:45调整。

LocalDateTime.parse( 
    "19/10/2014 00:45:00" , 
    DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" )   // Returns a `DateTimeFormatter` object. 
)                                                          // Returns a `LocalDateTime` object.
.atZone( 
    ZoneId.of( "America/Sao_Paulo" )                       // Returns a `ZoneId` object.
)                                                          // Returns a `ZonedDateTime` object.
.toString()                                                // Returns a `String` object holding text in standard ISO 8601 format extended to append the name of the time zone in square brackets.

2014-10-19T01:45-02:00 [美国/sao_paulo]

java.Time

现代方法使用 java.time 类,几年前取代了现在的遗产的可怕日期时间。

您的输入字符串缺少时区或从UTC上取消的指标。因此,解析为LocalDateTime

String input = "19/10/2014 00:45:00";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse( input , f );

LocalDateTime只是日期的日期。因此,此类不能代表一个时刻,而不是时间表上的点。要确定片刻,我们必须将LocalDateTime放置在时区的上下文中,从而产生ZonedDateTime对象。

ZoneId z = ZoneId.of( "America/Sao_Paulo" );
ZonedDateTime zdt = ldt.atZone( z );

转储到控制台。

System.out.println( "ldt = " + ldt );
System.out.println( "zdt = " + zdt );

运行时。

ldt = 2014-10-19T00:45

ZDT = 2014-10-19T01:45-02:00 [America/Sao_paulo]

我们可以看到 java.time 进行了必要的调整。00:45的时间更改为01:45。

请确保在此调整中了解 java.time 使用的逻辑。研究Javadoc。只有您才能确定这样的调整是否适合您的业务逻辑。

日期源自用户输入或存储信息?请注意,将GMT-3设置为JVM与" America/Sao_paulo"不同。我不认为GMT观察到夏令时。切换JVM来回设置看起来不像一个好的解决方案。如果只是存储的信息,您可以向后1小时更新值,不确定这里是哪种情况。设置GMT-3时区是我看到的唯一解释,即在美国/sao_paulo时区达到无效日期。

相关内容

  • 没有找到相关文章

最新更新