首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >巴西DST期间出现日期解析异常

巴西DST期间出现日期解析异常
EN

Stack Overflow用户
提问于 2015-05-07 01:23:12
回答 3查看 616关注 0票数 2

进入巴西DST时间段时,时钟向前拨1小时。2014年,DST从19/10开始,所以时间从19/10/2014 00:00:00变成了2015/10/19 01:00:00。“不存在”之间的句号。

因此,当使用美国时区/圣保罗解析日期"19/10/2014 00:45:00“时,会抛出解析异常: java.text.ParseException: Unparseable date:"19/10/2014 00:45:00”。

代码语言:javascript
复制
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));

美国/圣保罗时区应该支持DST更改。此问题的预期修复方案是什么?当DST周期开始和结束时,我必须手动更改jvm时区吗?目前的“修复”是在DST周期开始时将jvm时区更改为GMT-2。

注意:这个问题源于一个用spring开发的应用程序。示例日期在从字符串转换为java.util.Calendar时抛出异常。在上面的示例代码中,我将lenient设置为false,以便能够重现错误。

EN

回答 3

Stack Overflow用户

发布于 2015-05-07 05:23:25

java.util.Calendar表示时间上的一个瞬间。那个瞬间必须存在。当本地时间值落入向前跳跃DST间隙时,这些值不会表示为时间的真实时刻。换句话说,在巴西正确配置的时钟永远不会在2014年10月19日显示00:45:00。因此出现了例外情况。有关可视化表示,请参见the DST tag wiki

由于您正在解析用户输入,因此我建议您将字符串解析为LocalDateTime而不是Calendar。对于Java7,您可以从Joda-Time获得这一点。对于Java8,这是内置到新的java.time包中的。

一旦你有了它的LocalDateTime,然后你就可以决定从那里开始。如果时间无效(落入向前跳跃转换的间隙),或者不明确(由于回退转换),您可以检测到这些情况,并决定如何在应用程序中处理它们。

票数 0
EN

Stack Overflow用户

发布于 2020-04-21 08:26:29

tl;dr

在考虑DST切换时,使用java.time从00:45调整为01:45。

代码语言:javascript
复制
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美国/圣保罗

java.time

现代方法使用多年前取代了现在遗留下来的可怕的日期-时间类的java.time类。

您的输入字符串缺少时区或与UTC的偏移量指示符。所以解析为LocalDateTime

代码语言:javascript
复制
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对象。

代码语言:javascript
复制
ZoneId z = ZoneId.of( "America/Sao_Paulo" );
ZonedDateTime zdt = ldt.atZone( z );

转储到控制台。

代码语言:javascript
复制
System.out.println( "ldt = " + ldt );
System.out.println( "zdt = " + zdt );

运行时。

ldt = 2014-10-19T00:45

zdt =2014-10-19T01:45-02:00美国/圣保罗

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

请务必理解java.time在此调整中使用的逻辑。研究Javadoc。只有你才能决定这样的调整对于你的业务逻辑是否正确。

票数 0
EN

Stack Overflow用户

发布于 2015-05-07 02:48:59

数据是来自用户输入还是存储的信息?请注意,将GMT-3设置为JVM与"America/Sao_Paulo“不同。我不相信格林尼治标准时间遵守夏令时。来回切换JVM设置看起来不是一个好的解决方案。如果它只是存储的信息,你可以提前一个小时向后更新值,不确定这里是哪种情况。设置GMT-3时区是我看到的在美国/圣保罗时区出现无效日期的唯一原因。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30083568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档