防止日期转换溢出

Posted

技术标签:

【中文标题】防止日期转换溢出【英文标题】:Preventing overflow on date conversion 【发布时间】:2017-10-10 19:22:52 【问题描述】:

在使用日期输入时,我们创建了一个我们认为非常错误的值:2017 年 2 月 45 日或“2017-02-45”。 这导致将溢出的天数添加到下个月,我们以 3 月的日期结束。 有没有办法廉价地检查这些日期不一致? 当前计划是将字符串转换为日期到文本并与原始值进行比较。 接下来是创建一个 Java UDF 并使用它来检查和测试格式。

【问题讨论】:

adding the overflow of days into the next month 是什么意思?将 2017-02-45 转换为日期将返回 null。 发布您的代码。通常使用至少三个日期时间框架,每个框架在这方面都有不同的行为。并解释与 Apace Hive 的联系(如此标记)。 我们看到的是 2017-02-45 变成了 ~2017 年 3 月 17 日的日期值。它不是空值。一些研究表明它类似于 DataFormat.setLenient(false)。 @user1281598 如果您的意思是java.text.DateFormat,那么该类是麻烦的旧日期时间类的一部分,这些类现在是遗留的,被 java.time 类所取代。避免使用DateCalendarDateFormat 类。 setLenient(false) 在旧的 DateFormat 中。 【参考方案1】:

tl;博士

使用现代 java.time 类。

使用ResolverStyle.STRICTSMART 解析通过LocalDate 时抛出的DateTimeParseException

详情

取决于您使用的日期时间类。

现代 java.time 类使用称为resolver style 的三种模式中的任何一种进行解析:

ResolverStyle.STRICT(默认) ResolverStyle.SMART ResolverStyle.LENIENT

解析“2017-02-45”时,默认的STRICT 会抛出java.time.format.DateTimeParseException

LocalDate.parse( "2017-02-45" )  

java.time.format.DateTimeParseException:无法解析文本“2017-02-45”:DayOfMonth 的值无效(有效值 1 - 28/31):45

SMART 同上,抛出异常。

只有LENIENT接受错误输入并进行调整。

输入:2017-02-45

输出:2017-03-17

参见this live code example in IdeOne.com,我们在其中尝试了三种模式。

String input = "2017-02-45" ;
System.out.println( "input: " + input ) ;

for( ResolverStyle rs : ResolverStyle.values() ) 

    try
        System.out.println( "---------------" ) ;
        System.out.println( "Parsing with ResolverStyle: " + rs ) ;
        DateTimeFormatter f = DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle( rs ) ;
        LocalDate ld = LocalDate.parse( input , f ) ;
        System.out.println( "ld.toString(): " + ld ) ;
     catch ( DateTimeParseException e ) 
        System.out.println( "Caught exception for ResolverStyle: " + rs ) ;
    


input: 2017-02-45
---------------
Parsing with ResolverStyle: STRICT
Caught exception for ResolverStyle: STRICT
---------------
Parsing with ResolverStyle: SMART
Caught exception for ResolverStyle: SMART
---------------
Parsing with ResolverStyle: LENIENT
ld.toString(): 2017-03-17

【讨论】:

以上是关于防止日期转换溢出的主要内容,如果未能解决你的问题,请参考以下文章

防止无效日期在jdk6中转换为下个月的日期?

如何防止 pandas 将原始数据库日期格式转换为 pandas 日期格式

环回将日期之类的字符串转换为日期,如何防止它

MySQL:防止“无法将MySQL日期/时间值转换为”系统日期时间;(无效Da)

Postgres 通过时区转换防止时间戳

如何将字符串日期列转换为 Google 大查询中的日期列?