經(jīng)常出現(xiàn)的8小時(shí)
在代碼中寫(xiě)到關(guān)于時(shí)間的問(wèn)題時(shí)經(jīng)常遇到一個(gè)惹人煩的8小時(shí)問(wèn)題再愈,這個(gè)就是因?yàn)槲覀兪窃跂|八區(qū) ,而有時(shí)候后端返給我們的時(shí)間是零時(shí)區(qū)的時(shí)間,東八區(qū)比零時(shí)區(qū)要早8小時(shí),比如現(xiàn)在東八區(qū)是中午十二點(diǎn),零時(shí)區(qū)就是凌晨四點(diǎn)流炕,那么我們就需要把零時(shí)區(qū)的時(shí)間轉(zhuǎn)化為東八區(qū)的時(shí)間。
首先看一個(gè)例子仅胞,獲取當(dāng)前時(shí)間字符串:
//通過(guò)[NSDate date]返回的一定是零時(shí)區(qū)的時(shí)間
NSDate *date = [NSDate date];
NSLog(@"date時(shí)間 = %@", date);
//如果沒(méi)有規(guī)定formatter的時(shí)區(qū)每辟,那么formatter默認(rèn)的就是當(dāng)前時(shí)區(qū),比如現(xiàn)在在北京就是東八區(qū)干旧,在東京就是東九區(qū)
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//最結(jié)尾的Z表示的是時(shí)區(qū)渠欺,零時(shí)區(qū)表示+0000,東八區(qū)表示+0800
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss Z"];
使用formatter轉(zhuǎn)換后的date字符串變成了當(dāng)前時(shí)區(qū)的時(shí)間
NSString *dateStr = [formatter stringFromDate:date];
NSLog(@"字符串時(shí)間 = %@", dateStr);
輸出:
2018-05-31 14:43:07.011223+0800 TimeDemo[4674:167771] date時(shí)間 = 2018-05-31 06:43:07 +0000
2018-05-31 14:43:07.011777+0800 TimeDemo[4674:167771] 字符串時(shí)間 = 2018-05-31 14:43:07 +080
很重要的一點(diǎn)就是椎眯,[NSDate date]返回的是零時(shí)區(qū)的時(shí)間挠将!返回的是零時(shí)區(qū)的時(shí)間胳岂!返回的是零時(shí)區(qū)的時(shí)間!
打印結(jié)果前面的時(shí)間是北京時(shí)間舔稀,為2018-05-31 14:43:07.011223乳丰,而通過(guò)[NSDate date]得到的時(shí)間是2018-05-31 06:43:07 +0000,后面的+0000就表示了這個(gè)時(shí)間是零時(shí)區(qū)的時(shí)間内贮,這個(gè)時(shí)間對(duì)應(yīng)的東八區(qū)的時(shí)間就是2018-05-31 14:43:07.011223 +0800了产园。這兩個(gè)時(shí)間是同一個(gè)時(shí)間,只不過(guò)時(shí)區(qū)不一樣夜郁。
formatter在不特意設(shè)置時(shí)區(qū)的情況下什燕,默認(rèn)時(shí)區(qū)是當(dāng)前地區(qū)的時(shí)區(qū),比如我們?nèi)绻谥袊?guó)竞端,當(dāng)前時(shí)區(qū)就是東八區(qū)秋冰,我們?nèi)绻咽謾C(jī)拿到東京,當(dāng)前時(shí)區(qū)就是東九區(qū)婶熬。經(jīng)過(guò)formatter轉(zhuǎn)化為時(shí)間字符串后時(shí)間就變成了當(dāng)前時(shí)區(qū)也就是東八區(qū)的時(shí)間2018-05-31 14:43:07 +080,也就沒(méi)有了8小時(shí)的誤差埃撵。
轉(zhuǎn)字符串時(shí)間的時(shí)區(qū)設(shè)置
上面例子中NSDate時(shí)間轉(zhuǎn)字符串時(shí)間時(shí)赵颅,NSDateFormatter并沒(méi)有設(shè)置時(shí)區(qū),而是使用當(dāng)前地區(qū)的時(shí)區(qū)暂刘,這和設(shè)置系統(tǒng)系統(tǒng)時(shí)區(qū)formatter.timeZone = [NSTimeZone systemTimeZone]的效果是一樣的饺谬。我們也可以規(guī)定一定使用某一個(gè)時(shí)區(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ū)時(shí)間
NSString *dateStr = [formatter stringFromDate:date];
NSLog(@"字符串時(shí)間 = %@", dateStr);
這樣不管我們的手機(jī)是在哪里,打印出來(lái)的時(shí)間都是東八區(qū)的時(shí)間谣拣。
還有如下的時(shí)區(qū)指定:
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Tokyo"];//東九區(qū)時(shí)間
formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];//零區(qū)時(shí)間
formatter.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];//零區(qū)時(shí)間募寨,和GMT一樣
字符串時(shí)間轉(zhuǎn)NSDate
字符串時(shí)間轉(zhuǎn)NSDate也會(huì)有時(shí)間問(wèn)題,看下面的例子:
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)了問(wèn)題轉(zhuǎn)后之后得到的時(shí)間的時(shí)區(qū)又變成了零時(shí)區(qū)森缠。問(wèn)題就出在拔鹰,凡是返回結(jié)果為NSDate類型的,得到的時(shí)間都是零時(shí)區(qū)贵涵,都是零時(shí)區(qū)列肢!都是零時(shí)區(qū)!
如果上面給出的字符串時(shí)間是@"2016-12-07 14:06:24 +0000"宾茂,也就是這個(gè)時(shí)間字符串的時(shí)區(qū)是零時(shí)區(qū)瓷马,那么得到的結(jié)果就不會(huì)有變化拣度。
NSDateFormatter的格式為@"yyyy-MM-dd HH:mm:ss Z"厉斟,這里面的Z表示的就是時(shí)區(qū),我們?cè)趥鬟f時(shí)間字符串的時(shí)候也要按照這個(gè)規(guī)則在時(shí)間后面加上+0800或者+0000這樣表示時(shí)區(qū)的员淫。
當(dāng)不指定字符串的時(shí)區(qū)時(shí)端盆,即NSDateFormatter的格式為@"yyyy-MM-dd HH:mm:ss"怀骤,這樣傳遞進(jìn)來(lái)的字符串的時(shí)區(qū)默認(rèn)為當(dāng)前時(shí)區(qū)费封,轉(zhuǎn)化為NSDate是零時(shí)區(qū)時(shí)間。
當(dāng)前時(shí)間轉(zhuǎn)時(shí)間戳
時(shí)間戳是指1970年1月1日0時(shí)0分0秒到當(dāng)前時(shí)間的秒數(shù)晒喷。注意這里的當(dāng)前時(shí)間是指零時(shí)區(qū)的NSDate時(shí)間孝偎。
NSDate *date = [NSDate date];
NSTimeInterval timeIn = [date timeIntervalSince1970];
NSLog(@"時(shí)間戳 = %.0f", timeIn);
打印結(jié)果:
2018-05-31 15:49:48.165702+0800 TimeDemo[5635:205558] 時(shí)間戳 = 1527752988
NSDate轉(zhuǎn)當(dāng)前時(shí)區(qū)的NSDate時(shí)間
NSDate *date = [NSDate date];
NSTimeZone *zone = [NSTimeZone systemTimeZone];
//獲得當(dāng)前時(shí)區(qū)和零時(shí)區(qū)的秒數(shù)偏移量
NSInteger interval = [zone secondsFromGMTForDate:date];
NSDate *localDate = [date dateByAddingTimeInterval:interval];
NSLog(@"localDate = %@",localDate);
時(shí)間戳和時(shí)間字符串的相互轉(zhuǎn)換
時(shí)間戳轉(zhuǎn)時(shí)間字符串
- (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;
}
時(shí)間字符串轉(zhuǎn)時(shí)間戳
- (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;
}