起因
作者在最近工作中需要向后臺上傳手機當(dāng)前日期,我很自然的就想到我們可以用NSDate來獲取當(dāng)前系統(tǒng)時間,于是就用下面的方法獲得了系統(tǒng)時間并轉(zhuǎn)換成了日期
NSDate *sourceDate = [NSDate date]
NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
[dateformatter setDateFormat:@"YYYY-MM-dd"];
[dateformatter stringFromDate:sourceDate]
但是,當(dāng)我在檢驗上傳數(shù)據(jù)是否正確的時候,把[NSDate date]在控制臺中輸出后,發(fā)現(xiàn)居然和正確時間有了8小時的時差。這顯然是項目不能接受的誤差,所以我嘗試將這8小時的誤差進行調(diào)整
嘗試
于是經(jīng)過一番Google,我發(fā)現(xiàn)網(wǎng)上好多人都遇到了這個問題,于是找到了下面的這種解決辦法
NSDate *sourceDate = [NSDate date];
NSTimeZone *sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSTimeZone *mytimeZone = [NSTimeZone systemTimeZone];
NSInteger sourceOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
NSInteger myTimeOffset = [mytimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval interval = myTimeOffset - sourceOffset;
NSDate *destinationDate = [[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate];
這時候我的destinationDate就是我認為“正確”的時間,但是當(dāng)我調(diào)用stringFromDate:時,然而發(fā)現(xiàn)坑爹的日期居然變成了明天的日期(發(fā)現(xiàn)問題時在下午)
正確的做法
在查看了蘋果關(guān)于NSDate和NSDateFormatter的文檔后,終于發(fā)現(xiàn),第二步的轉(zhuǎn)換完全是多此一舉。
文檔中明確的說明了
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).
也就是說,NSDate是沒有時區(qū)這個概念的,他只提供了一個UTC時間,與時區(qū)無關(guān),我們前面對NSDate的操作是強行給他加了8小時,并沒有改變時區(qū)。
而時區(qū)的概念是存在于NSDateFormatter中,在我們調(diào)用stringFromDate:時就已經(jīng)默認將UTC時間轉(zhuǎn)換成了我們所在的時區(qū),并不需要我們對[NSDate date]進行修改。
總結(jié)
我遇到這個蛋疼的問題后,我問了以前取過當(dāng)前日期的同事,發(fā)現(xiàn)他的代碼也存在同樣的問題,只是當(dāng)時測試并沒有發(fā)現(xiàn)。
沉痛的教訓(xùn)就是,遇到問題,還是首先認真看蘋果官方的文檔,然后再到網(wǎng)上去搜,網(wǎng)上的答案確實不一定是對的,有的時候只是把你從一個坑領(lǐng)到了另一個坑里。