【问题标题】:SimpleDateFormat fails to reject input missing century on the year of the input, despite "yyyy" in the formatting pattern尽管格式化模式中有“yyyy”,SimpleDateFormat 无法拒绝输入年份中缺少世纪的输入
【发布时间】:2010-12-10 15:44:34
【问题描述】:

我有一个带有yyyy-M-d" 模式的 SimpleDateFormat,以及以下场景:

String str = "02-03-04";        
SimpleDateFormat f = new SimpleDateFormat("yyyy-M-d");
f.setLenient(false);
System.out.println(f.parse(str));

输出为Sat Mar 04 00:00:00 EST 2

我的目标是只捕获格式为 2004-02-03 的日期并忽略 02-03-04。我认为模式中的 yyyy 需要 4 位数的年份,但显然情况并非如此。谁能解释为什么这不会引发解析异常?我希望它...

【问题讨论】:

  • 除了使用更具体的 API 之外,正则表达式也应该可以工作(只需检查它是否匹配,然后使用解析器)。
  • 我为这篇文章简化了问题。实际上,我有一堆匹配各种模式的日期格式。事后看来,也许正则表达式(或 JODA 时间)会更好......但这就是我现在所处的位置。
  • 如果它正在附加一些东西,那么我真的无法提出比首先使用正则表达式进行验证更好的方法(考虑到日期模式会捕获,每个日期模式编写一个正则表达式应该很容易格式中的其他错误?)。
  • 啊!或者您可以使用set2DigitYearStart 将其设置为“不可能”的值,就像将来荒谬的事情(尽管听起来太像 y2k),然后检查它(就像乔恩的回答所暗示的那样)

标签: java simpledateformat


【解决方案1】:

嗯,我可以从the docs解释:

对于解析,如果模式字母的数量超过 2 个,则按字面解释年份,而不考虑位数。因此,使用“MM/dd/yyyy”、“01/11/12”模式会解析到公元 12 年 1 月 11 日

Joda Time 可能会更严格 - 总的来说,它是一个更好的 API,IMO...

如果解析后年份小于 1000,您总是可以抛出异常...

【讨论】:

  • +1,这让我最近有点紧张,当我调试时看到我的日期是从10 开始的:|
  • 如果年份小于 1000 则抛出无效。如果用户真的想要它并输入0002-03-04怎么办?
  • 我同意使用 Joda Time 会更好。但这是我目前无法切换的应用程序的较大部分。不过,我肯定会考虑在未来切换。
  • 如果我想用两种不同的日期格式同时捕获 2004-02-03 和 02-03-04,有没有简单的方法可以做到这一点?
  • SimpleDateFormat 的这种行为太可笑了!如果解析器不遵守模式,那么拥有模式有什么意义?
【解决方案2】:

tl;博士

使用 java.time,具有该格式模式的输入会失败,正如您所期望的那样。

LocalDate
.parse(
    "02-03-04" ,
    DateTimeFormatter.ofPattern ( "uuuu-M-d" )
)

...抛出java.time.format.DateTimeParseException

java.time

您使用的类现在已被 JSR 310 中定义并内置于 Java 8 及更高版本的现代 java.time 类所取代。

LocalDate 类表示仅日期值,没有时间,也没有 time zoneoffset-from-UTC

按照您的要求定义自定义格式模式。使用DateTimeFormatter 类。

DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuu-M-d" );

尝试解析您的输入。

String input = "02-03-04";
LocalDate localDate = LocalDate.parse ( input , f );

我们遇到DateTimeParseException,在输入年份的缺失世纪失败。正如你所料。

线程“main”java.time.format.DateTimeParseException 中的异常:无法在索引 0 处解析文本“02-03-04”


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 2023-01-31
    • 2019-07-12
    • 2012-02-20
    • 2010-12-30
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多