我有字符串格式的日期,我想将其解析为实用日期。
var date ="03/11/2013"
我将其解析为:
new SimpleDateFormat("MM/dd/yyyy").parse(date)
但奇怪的是,如果我通过“03-08- 201309 hjhkjhk ”或“03- 88 -2013”或 43 < / strong> -88-201378“,它不会抛出错误,它会解析它。
为此,我必须编写正则表达式模式以检查日期的输入是否正确。 但为什么会这样呢?
代码:
scala> val date="03/88/201309 hjhkjhk"
date: java.lang.String = 03/88/201309 hjhkjhk
scala> new SimpleDateFormat("MM/dd/yyyy").parse(date)
res5: java.util.Date = Mon May 27 00:00:00 IST 201309
答案 0 :(得分:52)
您应该使用DateFormat.setLenient(false)
:
SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy");
df.setLenient(false);
df.parse("03/88/2013"); // Throws an exception
我不确定是否会抓住你想要的所有 - 我似乎记得即使setLenient(false)
它比你预期的更宽松 - 但它应该抓住无效的月份数字示例
我认为它不会捕获尾随文本,例如“03/01/2013 sjsjsj”。您可能会使用接受parse
的{{1}}重载,然后在解析完成后检查当前的解析索引:
ParsePosition
您还应该查看可能允许更严格解释的Joda Time API,并且无论如何都是一个更清晰的日期/时间API。
答案 1 :(得分:4)
Jon Skeet’s answer是正确的,并且在2013年撰写时是一个很好的答案。
但是,您在问题中使用的课程SimpleDateFormat
和Date
现在已经过时了,所以如果有人今天遇到类似的问题,恕我直言最好的答案就是改为使用the modern Java date & time API。
很抱歉,我无法编写Scala代码,因此您将不得不使用Java。我正在使用
private static DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy");
格式模式字母与您的问题相同,但含义略有不同。正如我们将要看到的,DateTimeFormatter
按字面意思取模式字母的数量。现在我们尝试:
System.out.println(LocalDate.parse(date, parseFormatter));
结果:
"03/11/2013"
按预期解析为2013-03-11
。我使用了现代LocalDate
类,这是一个代表没有时间的日期的类,正是我们在这里需要的。"03/88/2013 hjhkjhk"
会为DateTimeParseException
提供消息Text '03/88/2013 hjhkjhk' could not be parsed, unparsed text found at index 10
。很精确,不是吗?如果这是我们想要的,那么现代API只有解析部分字符串的方法。"03/88/201309"
提供Text '03/88/201309' could not be parsed at index 6
。我们要求一个4位数的年份并给它6位数,这导致了反对意见。显然它会在尝试将88解释为月中的某一天之前检测并报告此错误。"03/88/2013"
给出了Text '03/88/2013' could not be parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 88
。再次,请享受信息的信息。"03-08-2013"
(用连字符而不是斜线)给出Text '03-08-2013' could not be parsed at index 2
,这并不奇怪。索引2是第一个连字符的位置。 Jon Skeet解释说,过时的SimpleDateFormat
可能是宽松的,也可能是非宽容的。对于DateTimeFormatter
也是如此,实际上它有3个而不是2个解析器样式,称为“宽松”,“智能”和“严格”。但是,由于许多程序员都没有意识到这一点,我认为他们做出了一个很好的选择,即不要将'lenient'作为默认值('smart')。
如果我们想让格式化程序宽松一下怎么办?
private static DateTimeFormatter parseFormatter
= DateTimeFormatter.ofPattern("MM/dd/yyyy")
.withResolverStyle(ResolverStyle.LENIENT);
现在它还将"03/88/2013"
解析为2013-05-27
。我相信这就是旧班级也会做的事情:从3月初算起88天到5月27日。其他错误信息仍然是相同的。换句话说,它仍然反对未解析的文本,6位数年份和连字符。
问题:我可以在Java版本中使用现代API吗?
如果至少使用Java 6 ,则可以。