Java DateFormat.parse(字符串)如何处理非日期尾随文本?
如果Java DateFormat.parse(字符串)如何处理非日期尾随文本?,java,date,Java,Date,如果DateFormat类的Parse方法成功解析字符串开头的日期,则该方法将忽略尾随文本 API是回避的: 解析给定字符串开头的文本以生成日期。 该方法不能使用给定字符串的整个文本 我认为“可能”的意思是——“如果尾随文本存在并且不是日期的一部分(不能解释为这样)”。但看起来这个“五月”更不可预测 给定 此操作不正确(意外): 虽然这工作正常(如预期): 如果其余解析文本是数字,则似乎总是无法正确解析(给出不同的错误结果): 现在,setLenient()的行为如下: 如果(correct)d
DateFormat
类的Parse方法成功解析字符串开头的日期,则该方法将忽略尾随文本
API是回避的:
解析给定字符串开头的文本以生成日期。
该方法不能使用给定字符串的整个文本
我认为“可能”的意思是——“如果尾随文本存在并且不是日期的一部分(不能解释为这样)”。但看起来这个“五月”更不可预测
给定
此操作不正确(意外):
虽然这工作正常(如预期):
如果其余解析文本是数字,则似乎总是无法正确解析(给出不同的错误结果):
现在,setLenient()
的行为如下:
ParseException:Unparseable date:“2019-12-111”
,这也很奇怪(日期是正确的,API承诺忽略尾随文本)Date parse(String-source,ParsePosition-pos)
在上述所有情况下(包括对setLenient的反应)的行为与Date parse(String-source)
的行为完全相同,只有一个(也是预期的)异常,其中一个arg parse()抛出ParseException,而这两个arg parse()返回null(这是它对要解析的字符串开头不正确的日期格式的反应)
还值得注意的是,在调用mydateFormat.parse(“2019-12-11234”,pos)
(使用setLenient(true)),之后,pos.getIndex()
返回13-哪个点“超出”234部分,这意味着它将234部分视为新SimpleDataFormat(“yyyyy-MM-dd”)中“yyyyy-MM-dd”的“-”部分
另外,我知道这些都是过时的日期/时间API,我更喜欢java.time而不是日期/日历/日期格式等,但它仍然大量存在于遗留代码中,以支持不可重构的情况。当您将islenent设置为true并添加额外的数字时,格式化程序将尝试根据给定的值计算新的日期因此,df.parse(“2019-12-1189”)
将被解析为2019-12-01+1189天(1189/365=3.26),因此3月3日星期五00:00:00 MSK 2023看起来是正确的结果(我不知道这里的确切数学)
11234年也是如此,大约增加了30年
您也可以在2019-12-32和2019-13-01中尝试此功能,这两个版本都将转换为2020-01-01
尽管你自己已经说过了,但我想重申,不要使用SimpleDateFormat
。这是出了名的麻烦和过时
您对文档的引用需要与文档中的至少一点结合起来阅读。基本上,SimpleDateFormat
无法完成您希望它完成的任务
java.time
输出为:
2019-12-11
我认为这是您想要的结果。2019-12-11
已被解析为日期,2
已被忽略为尾随文本,而不是日期的一部分
使用SimpleDataFormat无法完成此操作
为了说明我的观点,我使用了一个不同的例子:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
df.setLenient(false);
System.out.println(df.parse("2019-12-013"));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(df.parse("2019-12-112"));
2019年东部时间12月13日星期五00:00:00
此行为已记录在案。除了您的报价,我们还需要阅读:
- Number:…对于解析,除非需要分隔两个相邻字段,否则将忽略模式字母的数量
因此,在我的示例中,由于dd
之后没有任何相邻字段,因此我们无法说服SimpleDateFormat
将013
作为数字13以外的任何内容读取
链接
- 解释如何使用java.time
SimpleDateFormat
在内部使用NumberFormat
的(特定于区域设置)实例来解析给定的日期。在我的例子中,它是DecimalFormat
的实例
调试SimpleDataFormat
揭示了其中的关键部分是:
if (obeyCount) {
if ((start+count) > text.length()) {
break parsing;
}
number = numberFormat.parse(text.substring(0, start+count), pos);
} else {
number = numberFormat.parse(text, pos);
}
给出您的第一个示例:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
df.setLenient(false);
System.out.println(df.parse("2019-12-013"));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(df.parse("2019-12-112"));
内部设置的submissioncount
为false
,因此始终对文本的整个部分调用numberFormat.parse()
。此示例也会发生同样的情况:
DateFormat df = new SimpleDateFormat("yyyyMMdd");
System.out.println(df.parse("201912112"));
我至少把后一个例子看作是一个可能的bug。但是设置<代码> Obje> < /C> >的逻辑是如此复杂,以至于我觉得它不值得深入探索(因为这个API有点过时)。
还要注意的是,setLenient(boolean)
不修改内部的NumberFormat
解析器,而只修改解析完成后发挥作用的Calendar
实例。其余内容,请参阅Joakim Danielson的答案。尝试调用setLenient(false)
,请参阅:我建议您不要使用SimpleDateFormat
。该类是出了名的麻烦和过时很久的类。相反,请使用DateTimeFormatter
和来自的其他类。我认为问题更多的是如何强制SimpleDateFormat
遵守提供的模式,即使输入的是尾随数字,正如-显然-setLenient(false)
没有。是的,这个问题似乎已经更新了几次。回答这个问题时,我可能已经加载了一个旧版本
if (obeyCount) {
if ((start+count) > text.length()) {
break parsing;
}
number = numberFormat.parse(text.substring(0, start+count), pos);
} else {
number = numberFormat.parse(text, pos);
}
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(df.parse("2019-12-112"));
DateFormat df = new SimpleDateFormat("yyyyMMdd");
System.out.println(df.parse("201912112"));