[英]Why does SimpleDateFormat.parse().getTime() return an incorrect (negative) value?
[英]Why does SimpleDateFormat parse incorrect date?
我有字符串格式的日期,我想將其解析為實用日期。
var date ="03/11/2013"
我將其解析為:
new SimpleDateFormat("MM/dd/yyyy").parse(date)
但奇怪的是,如果我傳遞“03-08-201309 hjhkjhk ”或“ 03-88 -2013”或43 -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
您應該使用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”。 您可能會使用接受ParsePosition
的parse
重載,然后在解析完成后檢查當前的解析索引:
ParsePosition position = new ParsePosition(0);
Date date = dateFormat.parse(text, position);
if (position.getIndex() != text.length()) {
// Throw an exception or whatever else you want to do
}
您還應該查看Joda Time API,這可能會允許更嚴格的解釋 - 並且無論如何都是一個通常更干凈的日期/時間API。
Jon Skeet的回答是正確的,並且在2013年撰寫時是一個很好的答案。
但是,您在問題中使用的類, SimpleDateFormat
和Date
,現在已經過時了,所以如果有人今天遇到類似的問題,恕我直言,最好的答案是改為使用現代Java日期和時間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/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'和'strict'。 但是,由於許多程序員都沒有意識到這一點,我認為他們做出了一個很好的選擇,就是不要將'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 ,則可以。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.