3

我收到一个表示日期的字符串,我需要将此字符串转换为日期,并验证该字符串是否为有效日期。

我收到字符串 33-12-2013 解析方法返回日期 01-01-2014,代码:

Date fechaVencimientoFormateada;
SimpleDateFormat formateador = new SimpleDateFormat( "dd-MM-yyyy" );
try
{
    fechaVencimientoFormateada = formateador.parse( "33-12-2013" );      
    System.out.println( formateador.format(fechaVencimientoFormateada) );
}
catch ( ParseException e )
{
    System.out.println("ERROR!");
}

输出:Thu Jan 02 00:00:00 COT 2014

我期待一个 ParseException,有什么想法吗?

和其他例子:

字符串日期:365-12-2013 输出:Sun Nov 30 00:00:00 COT 2014

字符串日期:1-24-2013 输出:Mon Dec 01 00:00:00 COT 2014

为什么 ParseException 没有抛出?

4

3 回答 3

10

确保您setLenient(false)SimpleDateFormat. 否则它将毫无例外地解析大量无效日期,并且您不能太相信输出。

于 2013-11-29T14:32:47.070 回答
1

解析器将尽可能地解析您的输入,除非您将其lenient标志定义为false,在这种情况下,解析器将严格遵守您提供的模式。默认情况下(在您的情况下),此标志设置为true,这意味着输入中的任何不连贯都会尝试被挽救,如果您不太了解它是如何工作的,则会导致意外输出。

“尽他所能”我的意思是:

通过宽松的解析,解析器可以使用启发式方法来解释不精确匹配该对象格式的输入。

让我们看一下您的示例:

字符串日期:365-12-2013 输出:Sun Nov 30 00:00:00 COT 2014

允许的最大天数、月数或年数之间的超出差距,将以超出的特定单位添加。在这种情况下,您可以一直到 12 月 31 日,因为“溢出”的字段是这一天。您将有 31 天的时间来设置,还有 334 天的时间,这些天数仍将添加为天数。

长话短说:334天December 31, 2013之后November 30, 2014

字符串日期:1-24-2013 输出:Mon Dec 01 00:00:00 COT 2014

在这种情况下,原理相同,但适用于月份。在这种情况下,可能的最大月份为 12 个月,因此,如果还剩 12 个月,您实际上是在日期上增加了一年。导致您收到的输出。

将该lenient标志设置为false将强制严格遵守该模式,并且您寻求的异常将被正确抛出。

于 2013-11-29T14:45:11.267 回答
0

该类SimpleDateFormat实现了鲁棒性原则

在你所做的事情上保持保守,在你从别人那里接受的事情上保持自由

实现者可能知道 POSIX 的大多数 Unix 实现的行为mktime,它们具有类似的行为。

这是否明智值得商榷

于 2015-08-27T10:50:06.303 回答