經(jīng)常出現(xiàn)的8小時
在代碼中寫到關(guān)于時間的問題時經(jīng)常遇到一個惹人煩的8小時問題,這個就是因為我們是在東八區(qū) ,而有時候后端返給我們的時間是零時區(qū)的時間,東八區(qū)比零時區(qū)要早8小時,比如現(xiàn)在東八區(qū)是中午十二點,零時區(qū)就是凌晨四點,那么我們就需要把零時區(qū)的時間轉(zhuǎn)化為東八區(qū)的時間。
首先看一個例子,獲取當(dāng)前時間字符串:
//通過[NSDate date]返回的一定是零時區(qū)的時間
NSDate *date = [NSDate date];
NSLog(@"date時間 = %@", date);
//如果沒有規(guī)定formatter的時區(qū),那么formatter默認的就是當(dāng)前時區(qū),比如現(xiàn)在在北京就是東八區(qū),在東京就是東九區(qū)
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//最結(jié)尾的Z表示的是時區(qū),零時區(qū)表示+0000,東八區(qū)表示+0800
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
使用formatter轉(zhuǎn)換后的date字符串變成了當(dāng)前時區(qū)的時間
NSString *dateStr = [formatter stringFromDate:date];
NSLog(@"字符串時間 = %@", dateStr);
輸出:
2018-05-31 14:43:07.011223+0800 TimeDemo[4674:167771] date時間 = 2018-05-31 06:43:07 +0000
2018-05-31 14:43:07.011777+0800 TimeDemo[4674:167771] 字符串時間 = 2018-05-31 14:43:07 +080
很重要的一點就是,[NSDate date]返回的是零時區(qū)的時間!返回的是零時區(qū)的時間!返回的是零時區(qū)的時間!
打印結(jié)果前面的時間是北京時間,為2018-05-31 14:43:07.011223,而通過[NSDate date]得到的時間是2018-05-31 06:43:07 +0000,后面的+0000就表示了這個時間是零時區(qū)的時間,這個時間對應(yīng)的東八區(qū)的時間就是2018-05-31 14:43:07.011223 +0800了。這兩個時間是同一個時間,只不過時區(qū)不一樣。
formatter在不特意設(shè)置時區(qū)的情況下,默認時區(qū)是當(dāng)前地區(qū)的時區(qū),比如我們?nèi)绻谥袊?dāng)前時區(qū)就是東八區(qū),我們?nèi)绻咽謾C拿到東京,當(dāng)前時區(qū)就是東九區(qū)。經(jīng)過formatter轉(zhuǎn)化為時間字符串后時間就變成了當(dāng)前時區(qū)也就是東八區(qū)的時間2018-05-31 14:43:07 +080,也就沒有了8小時的誤差。
轉(zhuǎn)字符串時間的時區(qū)設(shè)置
上面例子中NSDate時間轉(zhuǎn)字符串時間時,NSDateFormatter并沒有設(shè)置時區(qū),而是使用當(dāng)前地區(qū)的時區(qū),這和設(shè)置系統(tǒng)系統(tǒng)時區(qū)formatter.timeZone = [NSTimeZone systemTimeZone]的效果是一樣的。我們也可以規(guī)定一定使用某一個時區(qū):
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];//東八區(qū)時間
NSString *dateStr = [formatter stringFromDate:date];
NSLog(@"字符串時間 = %@", dateStr);
這樣不管我們的手機是在哪里,打印出來的時間都是東八區(qū)的時間。
還有如下的時區(qū)指定:
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Tokyo"];//東九區(qū)時間
formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];//零區(qū)時間
formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];//零區(qū)時間,和GMT一樣
字符串時間轉(zhuǎn)NSDate
字符串時間轉(zhuǎn)NSDate也會有時間問題,看下面的例子:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
NSDate *newDate = [formatter dateFromString:@"2016-12-07 14:06:24 +0800"];
NSLog(@"newDate = %@", newDate);
打印結(jié)果:
2018-05-31 15:22:11.878915+0800 TimeDemo[5236:189492] newDate = 2016-12-07 06:06:24 +0000
我們看到這樣轉(zhuǎn)化后就出現(xiàn)了問題轉(zhuǎn)后之后得到的時間的時區(qū)又變成了零時區(qū)。問題就出在,凡是返回結(jié)果為NSDate類型的,得到的時間都是零時區(qū),都是零時區(qū)!都是零時區(qū)!
如果上面給出的字符串時間是@"2016-12-07 14:06:24 +0000",也就是這個時間字符串的時區(qū)是零時區(qū),那么得到的結(jié)果就不會有變化。
NSDateFormatter的格式為@"yyyy-MM-dd HH:mm:ss Z",這里面的Z表示的就是時區(qū),我們在傳遞時間字符串的時候也要按照這個規(guī)則在時間后面加上+0800或者+0000這樣表示時區(qū)的。
當(dāng)不指定字符串的時區(qū)時,即NSDateFormatter的格式為@"yyyy-MM-dd HH:mm:ss",這樣傳遞進來的字符串的時區(qū)默認為當(dāng)前時區(qū),轉(zhuǎn)化為NSDate是零時區(qū)時間。
當(dāng)前時間轉(zhuǎn)時間戳
時間戳是指1970年1月1日0時0分0秒到當(dāng)前時間的秒數(shù)。注意這里的當(dāng)前時間是指零時區(qū)的NSDate時間。
NSDate *date = [NSDate date];
NSTimeInterval timeIn = [date timeIntervalSince1970];
NSLog(@"時間戳 = %.0f", timeIn);
打印結(jié)果:
2018-05-31 15:49:48.165702+0800 TimeDemo[5635:205558] 時間戳 = 1527752988
NSDate轉(zhuǎn)當(dāng)前時區(qū)的NSDate時間
NSDate *date = [NSDate date];
NSTimeZone *zone = [NSTimeZone systemTimeZone];
//獲得當(dāng)前時區(qū)和零時區(qū)的秒數(shù)偏移量
NSInteger interval = [zone secondsFromGMTForDate:date];
NSDate *localDate = [date dateByAddingTimeInterval:interval];
NSLog(@"localDate = %@",localDate);
時間戳和時間字符串的相互轉(zhuǎn)換
時間戳轉(zhuǎn)時間字符串
- (NSString *)convertToTimeStringWithTimeInterval:(NSTimeInterval)timeInterval{
NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
NSString *dateStsring = [dateFormatter stringFromDate:date];
return dateStsring;
}
時間字符串轉(zhuǎn)時間戳
- (NSTimeInterval)convertToTimeIntervalWithTimeString:(NSString *)timeString{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
NSDate *date = [dateFormatter dateFromString:timeString];
NSTimeInterval timeInterval = [date timeIntervalSince1970];
return timeInterval;
}