2012-06-30 219 views
9

我想在我的應用程序中使用NSDateFormatter,該應用程序需要一個日期字符串並將其格式化爲一個NSDate,以便我可以進行日期比較,但是我在查找時使用dateFromString並將其格式化爲日期失去一天。NSDateFormatter dateFromString返回不正確的日期

NSString *dateString = @"02-06-2012"; 
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"dd-MM-yyyy"]; 
NSDate *dateFromString = [[NSDate alloc] init]; 
dateFromString = [dateFormatter dateFromString:dateString]; 
NSLog(@"My Date = %@", dateFromString); 
[dateFormatter release]; 

它輸出到控制檯:

我的日期= 2012-06-01 23:00:00 +0000

回答

19

我不要相信德魯夫的答案是正確的。事實上,目前尚不清楚有什麼問題。你似乎對所發生的事情和/或對發生的事情的解釋有不正確的期望。

NSDate代表某個時刻。這一刻沒有一個獨特的名字。它會在不同的地方和不同的命名系統(時區,日曆)中以不同的名稱出現。 NSDate不處理任何本,只是一瘸一拐在其-description方法,它具有產生那一刻的字符串表示。

其次,像一個字符串「2012年2月6日」不及時指定一個精確的時刻。首先,這只是一個沒有時間信息的日期,因此NSDateFormatter只是默認爲該日期的第一時刻。其次,它沒有指定時區。日曆日的第一時刻是每個時區的不同時刻。除非你指定一個時區與-setTimeZone:或字符串本身帶有時區信息,NSDateFormatter假定你問它來解析任何日期字符串在當前時區。

所以,你dateFromString對象表示在指定的日期,2012年2月6日的第一刻起,在您的時區。我希望這是你想要的。然而,當你記錄日誌時,你會被NSDate描述的方式困惑。正如我所說的,NSDate有挑選一些「名」(字符串表示)爲它所代表的時刻,其命名爲挑選是非常隨意的。這幾天它正在選擇UTC時刻已知的名稱。我從您的問題中顯示的日誌輸出中收集您位於UTC + 0100的信息。所以,日期可能看起來早一天,但它確實與您指定的時間相同。換句話說,「2012-06-01 23:00:00 +0000」和「2012-06-02 00:00:00 +0100」是完全相同時刻的兩個等同名稱。你不習慣看到第一張,並誤解了它。

經驗教訓是,你必須停止依靠NSDate的自我描述,以在任何特定的時區。真的,你不得不依賴任何關於它的東西,因爲它沒有記錄。實際上,-[NSDate description]的文檔聲明:「該表示不保證在操作系統的不同版本中保持不變。」

Dhruv直升機的解決方案似乎幫助僅僅是因爲它會導致NSDateFormatter-[NSDate description]對時區一致。但那是不可靠的。例如,它不適用於Snow Leopard,因爲-[NSDate description]在該版本的框架中使用本地時區而不是UTC。

更重要的是,它改變了從NSDateFormatter對日期字符串的解釋中獲得的NSDate對象表示的實際時刻。我懷疑你真的希望這具有特定的含義 - 你希望字符串被解釋爲在當地時區 - 他的解決方案會阻礙你的意圖。博士:你一直得到你想要的日期;不要依賴-[NSDate description];不要使用Dhruv的解決方案

+0

嗨,肯,謝謝你的詳細回覆,你會推薦我做什麼或使用?在我的應用程序中,我需要檢查是否等於或大於需要放入我的應用程序的特定硬編碼日期。謝謝 – MonkeyBlue

+1

你必須決定你真正意義的時刻。硬編碼日期是否意味着被解釋爲處於某個特定的固定時區(如貴公司的總部)?或者它應該被解釋爲在用戶的時區?如果是前者,則應在日期格式化程序上設置固定時區。如果是後者,則可以將其保留爲默認值,或者可以將其明確設置爲'[NSTimeZone defaultTimeZone]'(或'+ systemTimeZone')。 –

+0

謝謝肯我會給出一個去 - 固定時間基本上是一個特定的日期,所以如果你打開應用程序和你的基地在世界任何地方它應該使用具體的日期,看看今天是否更大或相等,我們這樣做因爲我們必須在某個日期顯示我們的應用中的不同信息。你的解釋也更有意義,所以我會標記你的答案。謝謝 – MonkeyBlue

49

嘗試添加該行代碼,

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0:00"]]; 

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; 

SWIFT更新:

從quetion代碼,

let dateString = "02-06-2012" 
var dateFormatter = NSDateFormatter() 
dateFormatter.dateFormat = "dd-MM-yyyy" 
var dateFromString : NSDate = dateFormatter.dateFromString(dateString)! 
println("My Date \(dateFromString)") 

和解決方案,

dateFormatter.timeZone = NSTimeZone(name: "GMT") 

OR

dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00") 
+0

謝謝你的完美。 – MonkeyBlue

+0

這不是一個非通用的解決方案嗎?如果設備不在格林威治時間,該怎麼辦? – Stavash

+4

@stavash就是這一點,GMT與UTC或世界時間相同。這是每個人都可以使用的一個標準化時區,並且它永遠不會改變(由於夏令時等)。這是iOS如何存儲日期/時間.... – lnafziger

相關問題