NSDate 時間比較中的時區問題.

midmirror醬發表於2019-03-28

判斷兩個時間是否是同一天,是無法用時間戳對比的,兩個時間戳間隔在24小時之內不能代表是同一天。

用時間戳對比,也是要計算是否同一年,同一月,同一日,才能判斷出是否同一天。

所以通常對比兩個時間是用 NSDate 來對比,但是要注意:NSDate 的時間實際上有某個時區的時間的含義,通過 [NSDate date] 建立出來的時間預設是零時區時間,但是這並不意味著兩個 NSDate 比較(判斷是否同一天)就一定會有正確的結果。

NSDate 比較是否是同一天,本質是比較 NSDateComponents 的 day month year 是否都相等。

比如:

- (BOOL)isSameDayWithDate:(NSDate *)date
{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    unsigned unitFlag = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
    NSDateComponents *comp1 = [calendar components:unitFlag fromDate:self];
    NSDateComponents *comp2 = [calendar components:unitFlag fromDate:date];
    return (([comp1 day] == [comp2 day]) && ([comp1 month] == [comp2 month]) && ([comp1 year] == [comp2 year]));
}
複製程式碼

網路上很多文章都介紹對 NSDate 或者 NSCalendar 做了擴充套件,來判斷某個日期是否是今天、昨天、明天。實際上 NSCalendar 在 ios(8.0) 開始提供了幾個官方方法。

- (BOOL)isDateInToday:(NSDate *)date;

- (BOOL)isDateInYesterday:(NSDate *)date;

- (BOOL)isDateInTomorrow:(NSDate *)date;
複製程式碼

但是考慮到使用者是可以修改手機時間的,通常我們會使用 ntp 時間作為標準時間,而不直接使用手機時間。

NSCalendar 也有提供了一個方法可以直接對比兩個時間。

/*
	This API compares the Days of the given dates, reporting them equal if they are in the same Day.
*/
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 API_AVAILABLE(macos(10.9), ios(8.0), watchos(2.0), tvos(9.0));
複製程式碼

但是,在實際場景中,比較兩個 NSDate 是否是同一天的時候,通常需要兩個 NSDate 同時處於當地時區才有意義。

同樣的兩個時間,在一個時區是同一天,在另一個時區很可能不是同一天!!!

如果你在東八區,用兩個零時區的時間來對比,是會出很大的問題的。

舉個例子:

today 1553741981 零時區 2019-03-28 02:59:41 +0000 (東八區 2019-03-28 10:59:41)
day   1553788800 零時區 2019-03-28 15:59:59 +0000 (東八區 2019-03-29 00:00:00)
複製程式碼

相關文章