NSTimeZone**時區是一個地理名字,是為了克服各個地區或國家之間在使用時間上的混亂。
基本概念:
GMT 0:00 格林威治標準時間; UTC +00:00 校準的全球時間; CCD +08:00 中國標準時間 [來自百度百科]
夏時制,英文”DaylightSavingTime”。夏季時將時區內的時間提前(一般為1小時),以節省資源,提高效率。使用夏時制期間,當前時區相對於GMT的時間偏移量會發生變化。在某些應用中可能需要考慮。
任何時區都以GMT為基準,即,任何NSTimeZone物件所代表的時區都是相對於GMT的,這裡的相對性是NSTimeZone中最重要的屬性,我們稱之為當前時區相對於GMT的偏移量。一旦知道了一個偏移量,便可以確定一個時區。在iOS中,偏移量是以”秒”為單位的。
NSTimeZone是一個類簇,我們所使用的任何NSTimeZone物件都是NSTimeZone的私有子類。
iOS中的時間類NSDate中儲存的時間,都是相對於GMT的,我們使用NSDate時,會根據App的時區設定返回與時區對應的資料。
iOS系統中的/usr/share/zoneinfo/目錄中儲存了所有的可根據 地理位置名稱 或 時區別名 得到的時區資訊。時區別名都是與具體的地理位置一一對應的。(已越獄的童鞋請看)
iOS中的時區表示方法:GMT+0800 GMT-0800。(+:東區 -:西區 08:小時數 00:分鐘數)。 GMT+0830就是指比GMT早8小時外加30分鐘的時區。
由方法理解NSTimeZone
1.第一批
// 這個方法的名字很委婉,known一詞說明這是“他”已知的時區的名字。世界各地對自己所在的時區可能都有一定的命名,但是不一定被“他”收錄。例如,中國大陸,只有重慶和上海被收錄了(難道這是中國只使用一個時區的錯誤?!)。使用這個方法獲得的時區名字,都是在iOS系統中/usr/share/zoneinfo/目錄中儲存時區資料。隨著iOS版本的更新,這裡面的資料會發生變動。當然,要是你的裝置越獄了,你可以手動往該目錄下新增時區檔案。
// 時區檔案裡面包括了一下內容:
// 當前時區相對於GMT的偏移量(s)
// 當前時區的名字縮寫
// 當前時區是否使“夏時制”時區
// 因為時區檔案中包含了"偏移量",所以通過“時區的名稱”可以指定一個“時區”。
// 時區名稱舉例:
// Africa/Abidjan
// America/New_York
// Asia/Shanghai
// Asia/Hong_Kong
// 越獄的童鞋可以看出時區的名稱和/usr/share/zoneinfo中的目錄結構基本一一對應。
+(NSArray *)knownTimeZoneNames;
// 獲取所有的時區名稱縮寫
// 名稱縮寫與名稱是一一對應的關係,例如:HKT = "Asia/Hong_Kong";
// 預設情況下,呼叫該方法回去/usr/share/zoneinfo目錄下找時區名稱縮寫,但是當使用方法"+ (void)setAbbreviationDictionary:(NSDictionary *)dict;"後,將會只返回剛才設定的時區名稱縮寫。請看下文的程式碼例項!
// 名稱縮寫舉例:
// EST = "America/New_York";
// GMT = GMT;
// GST = "Asia/Dubai";
// HKT = "Asia/Hong_Kong";
+(NSDictionary *)abbreviationDictionary;
2.第二批
// 由時區的名稱獲得對應的NSTimeZone物件
// 通過時區名稱可以獲得時區檔案,通過時區檔案就可以獲得“偏移量”,“名稱縮寫”,“是否使用夏時制”等資訊。
+(id)timeZoneWithName:(NSString *)tzName;
// 由時區名稱縮寫獲得對應的NSTimeZone物件
// 這裡的時區名稱縮寫有兩種情況:
// 第一種是上面說的HKT這樣的縮寫,與時區名稱一一對應,通過這樣的縮寫獲得的NSTimeZone物件,與使用時區名稱獲得得NSTimeZone物件一樣。(大概讀取得是同一個時區檔案)
// 第二種是"GMT+0800"這樣格式得縮寫,其實這就是偏移量。通過偏移量在iOS中是不能讀到與之對應得時區檔案的,因此就無法知道“時區名稱”,“名稱縮寫”,“是否使用夏時制”這樣的資訊了。預設情況下,"時區名稱"和"名稱縮寫"都會賦值為"GMT+0800","是否使用夏時制"則不會設定(預設不使用)。
+(id)timeZoneWithAbbreviation:(NSString *)abbreviation;
// 由偏移量獲得對應的NSTimeZone物件
// 只說一點:通過偏移量獲得的NSTimeZone物件的“市區名稱”,“名稱縮寫”都會賦值為"GMT+0800","是否使用夏時制"則不會設定(預設不使用)。
// 注意!!!!該方法不做引數的範圍檢查!!!
+(id)timeZoneForSecondsFromGMT:(NSInteger)seconds; // 不做安全性檢查
NSTimeZone的屬性變數(猜想):
// 當前時區與GMT的偏移量,以秒為單位 可通過方法"- (NSInteger)secondsFromGMT;"獲取,中國標準時區的偏移量為(8*60*60)。
// 這是NSTimeZone類中最基本的屬性,類似於NSDate中的_secondsSinceRef屬性。
// 其他的屬性都是為了豐富NSTimeZone,以實現offset與具體的地理位置以及與時區相關的其他資訊的繫結。
// 對應方法:- (NSInteger)secondsFromGMT;
int offset;
// 時區的名稱,
// 對應方法:- (NSString *)name;
NSString *_name;
// 時區名稱縮寫
// 對應方法:- (NSString *)abbreviation;
NSString *abbrev;
// 時區檔案資料
// 對應方法:- (NSData *)data;
NSData *_data;
// 時區是否使用夏時制
// 對應方法:- (BOOL)isDaylightSavingTime;
BOOL is_dst;
程式碼例項:
時區對時間的影響
// 修改預設時區會影響時間的輸出顯示
[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0900"]]; // 只能夠修改該程式的defaultTimeZone,不能修改系統的,更不能修改其他程式的。
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *now = [NSDate date];
NSLog(@"now:%@", [dateFormatter stringFromDate:now]);
// 也可直接修改NSDateFormatter的timeZone變數
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];
NSLog(@"now:%@", [dateFormatter stringFromDate:now]);
新增中國標準時間名稱縮寫
// 設定並獲取時區的縮寫
NSMutableDictionary *abbs = [[NSMutableDictionary alloc] init];
[abbs setValuesForKeysWithDictionary:[NSTimeZone abbreviationDictionary]];
[abbs setValue:@"Asia/Shanghai" forKey:@"CCD"];
[NSTimeZone setAbbreviationDictionary:abbs];
NSLog(@"abbs:%@", [NSTimeZone abbreviationDictionary]);
夏天了!注意夏時制!
// 因為“夏時制”而產生的方法
-(NSInteger)secondsFromGMTForDate:(NSDate *)aDate;
-(NSString *)abbreviationForDate:(NSDate *)aDate;
-(BOOL)isDaylightSavingTimeForDate:(NSDate *)aDate;
-(NSTimeInterval)daylightSavingTimeOffsetForDate:(NSDate *)aDate NS_AVAILABLE(10_5, 2_0);
-(NSDate *)nextDaylightSavingTimeTransitionAfterDate:(NSDate *)aDate NS_AVAILABLE(10_5, 2_0);