關於NSDate,NSDateFormatter,NSTimeZone的一些通俗理解
基礎概念
1.GMT 0:00 格林威治標準時間; UTC +00:00 校準的全球時間; CCD
+08:00 中國標準時間
2.iOS中的時間類NSDate中儲存的時間,都是相對於GMT的,我們使用NSDate
時(NSDate必須是0時區的,UTC格式的),會根據App設定的當前時區設定返回
與時區對應的資料。
3.iOS中的時區表示方法:GMT+0800 GMT-0800。(+:東區 -:西區 08:小
時數 00:分鐘數)。 GMT+0830就是指比GMT早8小時外加30分鐘的時區。
4.世界標準時間,國際協調時間,簡稱UTC。不屬於任意時區
5.系統認為NSDate是0時區的,NSString是東八區的
簡單說下個人的理解 根據時區可以看到,我們在東八區,時間點比國際標準時間快八小時,而LA在在西7區,時間慢7小時,因此,同一時間下,你切換手機座標,你獲取的時間戳美國比中國的大,因為時間戳的計算都是根據0時區來算的,中國的要減去,美國自然要加上了,有個簡單的例子,如果你預設NSDate TimeZone下,你切換計算時間戳是沒有問題,但是如果你用東八區的時間戳去使用,肯定比實際上多出來八小時,這個時候如果要上傳給伺服器,那就尷尬了哈。。。如果你手動切換時區,記得算好時間戳。下面會給例子,有個很重要的思想就是,顯示的時候用NSString,但是內部涉及到計算,比較,時間戳的問題,都是要NSDate,這樣保證計算出來的東西肯定不會錯
程式碼示例一:不同時區之間的時間轉換
// 獲取usr/share/zoneinfo目錄下所有已知的時區
NSArray *arr = [NSTimeZone knownTimeZoneNames];
// 獲取所有時區的縮寫
NSDictionary *dict = [NSTimeZone abbreviationDictionary];
NSLog(@"%@",dict);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
NSString *timeStr = @"2017-05-10";
NSDate *currentDate = [dateFormatter dateFromString:timeStr];
NSLog(@"需要格式化的時區--->%@,格式後的Date--->%@",dateFormatter.timeZone,currentDate);
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDate *currentDate1 = [dateFormatter dateFromString:timeStr];
NSLog(@"需要格式化的時區--->%@,格式後的Date--->%@",dateFormatter.timeZone,currentDate1);
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/Los_Angeles"]];
NSDate *currentDate2 = [dateFormatter dateFromString:timeStr];
NSLog(@"需要格式化的時區--->%@,格式後的Date--->%@",dateFormatter.timeZone,currentDate2);
/*
2017-05-05 14:32:13.893 NSData[10583:4643459] 需要格式化的時區--->Asia/Shanghai (GMT+8) offset 28800,格式後的Date--->2017-05-09 16:00:00 +0000
個人理解:
時間資訊都是針對於GMT標準時區來的,那麼NSDate是根據當前設定的時區來進行計算的,那麼例如上面的時間,預設是上海東八區的話就是向前移動8小時就是0時區的時間,所以列印出來的就是少8小時
OK,我們來設定下dateFormatter的時區為GMT和PDT(美國洛杉磯西七區),也就是NSDate預設為你就在標準時區的座標下,你給出來的時間根本不需要進行時區的轉換,直接顯示出來接即可,但是PDT的情況下是西區,時間比0區小,因此要加上7小時
2017-05-05 15:01:52.121 NSData[10996:4659886] 需要格式化的時區--->GMT (GMT) offset 0,格式後的Date--->2017-05-10 00:00:00 +0000
2017-05-05 15:01:52.124 NSData[10996:4659886] 需要格式化的時區--->America/Los_Angeles (PDT) offset -25200 (Daylight),格式後的Date--->2017-05-10 07:00:00 +0000
*/
這一坨簡單的程式碼和上面的圖一結合,應該非常清楚的能明白
首先,NSDate是計算0時區的時間,預設情況下NSDateFormmater是獲取當前手機設定的時區(我們們的是東八區),因此,這就解釋了預設情況下你轉換的時間NSDate比字串少了八個小時,但是如果你手動表示,你就在GMT,那就不需要轉換了,直接顯示字串時間,但是如果你說你在LA,西區,自然要加上7小時了
程式碼示例二:String和Date轉換
// 最簡單的NSDate和NSString的轉換
NSString *timeStr1 = @"2017-5-20";
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:@"yyyy-MM-dd"];
NSDate *date1 = [dateFormatter1 dateFromString:timeStr1];
// 加上了這句話 轉換的時候無需再算上時區,直接轉換
// [dateFormatter1 setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSString *resultStr = [dateFormatter1 stringFromDate:date1];
NSLog(@"%@,%@",date1,resultStr);
這簡單例子告訴我們,預設不設定時區的情況下,如果你在天朝東八區,你用的時間字串,轉換成NSDate(無論如何算出來的都是GMT/UTC國際標準時間0時期的時間)的時候會減去八小時,但是轉換成NSString的時候又會轉換成GMT標準時間下的(加上了八小時當前時期東八區)字串,系統認為NSDate是0時區的,NSString是東八區的
程式碼示例三:反面教材,可以用TimeZone進行時區切換操作更好
NSDate *date3 = [NSDate date];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間1%@",date3);
NSDate *date4 = [NSDate dateWithTimeIntervalSinceNow:0];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間2%@",date4);
NSDate *date5 = [NSDate dateWithTimeIntervalSinceNow:8*60*60];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間3加上今天此刻時間%@",date5);
NSDate *date6 = [NSDate dateWithTimeIntervalSinceNow:(8-24)*60*60];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間3昨天此刻時間%@",date6);
NSDate *date7 = [NSDate dateWithTimeIntervalSinceNow:(8+24)*60*60];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間3明天此刻時間%@",date7);
// 引數1比引數2小返回的是負數
NSTimeInterval timeIntervel = [date6 timeIntervalSinceDate:date7];
NSLog(@"NSDate(0時區標準時間 所在東八區,要減去八小時)----當前時間3昨天和明天時間間隔%.f",timeIntervel);
程式碼示例四:時間戳秒數轉換NSDate注意點
/*
不轉換的時候NSDate出來的肯定是沒有問題的0時區的時間
*/
NSDate *date8 = [NSDate date];
NSTimeInterval time8 = [date8 timeIntervalSince1970];
NSLog(@"%.f",time8);
NSDate *date9 = [NSDate dateWithTimeIntervalSince1970:1493968897];
NSLog(@"%@",date9);
// 這個例子只是說明,如果你用東八區的時間,然後你又手動修改了你當前的時區,你該到了GMT 0時區,這個時候的時間戳肯定比0時區多出八小時了,
// 你只要明白,正確的時間戳都針對GMT 0時區的國際標準時間為準的,如果前後臺需要涉及到時間上傳互動,你如果你手動切換了時區,需要注意時區
NSDate *date10 = [NSDate date];
NSDateFormatter *fotmatter10 = [[NSDateFormatter alloc] init];
[fotmatter10 setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *string10 = [fotmatter10 stringFromDate:date10];
[fotmatter10 setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDate *date100 = [fotmatter10 dateFromString:string10];
NSTimeInterval time10 = [date100 timeIntervalSince1970];
NSLog(@"%.f",time10);
NSDate *date11 = [NSDate dateWithTimeIntervalSince1970:1493998268];
NSLog(@"%@",date11);
程式碼示例五:時間轉換格式不對等相容問題
NSString *timeStringA = @"2017-05-05";
NSDateFormatter *formatterA = [[NSDateFormatter alloc] init];
[formatterA setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *dateA = [formatterA dateFromString:timeStringA];
NSString *timeStringB = @"2017-05-05 00:00:00";
NSDateFormatter *formatterB = [[NSDateFormatter alloc] init];
[formatterB setDateFormat:@"yyyy-MM-dd"];
NSDate *dateB = [formatterB dateFromString:timeStringB];
NSLog(@"-----%@",dateA);---> (null)
NSLog(@"-----%@",dateB);--->(null)
NSDate *dateC = [formatterB dateFromString:[self dateFormatWithoutTimeWithFormatString:@"yyyy-MM-dd" timesString:timeStringB]];
NSLog(@"%@",dateC);2017-05-04 16:00:00 +0000
// 當時間格式和formatter格式不對等的時候會出現null的情況,這個時候你對比時間計算就會出問題
- (NSString *)dateFormatWithoutTimeWithFormatString:(NSString *)formatString timesString:(NSString *)timeStr
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDateFormatter *dateFormatterNoYearAndSeconds = [[NSDateFormatter alloc] init];
[dateFormatterNoYearAndSeconds setDateFormat:formatString];
[dateFormatterNoYearAndSeconds setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
return [dateFormatterNoYearAndSeconds stringFromDate:[dateFormatter dateFromString:timeStr]]?:timeStr;
}
很簡單的知識點記錄下而已,網上有很多關於NSDate的擴充套件,很多都包裝好了,最近處理時間的時候列印看到了一些問題,就仔細看了下,一般來說都不會有問題,只是更加了解下時間時區之前的切換問題,明白一點就夠了,NSDate就是0時區的時間點,如果你不手動設定時區,預設我們們就是東八區,時間轉換成NSDate就會小八小時,但是轉換成NSString預設又會加上時區差,還有一點,切換時間的時候,從預設時區修改成了其他時區,你小心你的時間戳會有時區上的差異,記得最後比較下你轉換前的時區和轉換後的時區,預設的時間戳也是0時區為準的
相關文章
- 通俗理解一些概念
- 關於MySQL中的自聯結的通俗理解MySql
- 關於position的一些理解
- 關於position定位的一些理解
- 關於遊標的一些理解
- 關於Dart中Future的一些理解Dart
- 關於Swift中Properties的一些理解Swift
- 關於Base64的一些理解
- 關於服務高可用的一些理解
- 關於01揹包個人的一些理解
- 關於虛擬函式的一些理解函式
- 關於Oracle Cluster Software-----下面的解釋更通俗,容易理解Oracle
- 關於跨域和JSONP的一些理解跨域JSON
- 關於 Python 裝飾器的一些理解Python
- 關於排列熵的一些理解與解釋熵
- 關於 Node.js scoped module 的一些理解Node.js
- 關於 Python 裝飾器的一些個人理解Python
- 關於spring事務原始碼的一些小理解Spring原始碼
- 關於阿里JAVA開發手冊的一些理解阿里Java
- 關於Netty的一些理解、實踐與陷阱Netty
- 關於西門子間接定址的一些理解
- 關於Flutter空安全的一些使用經驗和理解Flutter
- 關於maven的核心pom(專案物件模型)的一些理解Maven物件模型
- 如何通俗的理解散度?
- 對maven的通俗理解,goodMavenGo
- 對於Fragment的一些理解Fragment
- 關於 DOM 的理解
- 關於Vuex的理解Vue
- 關於servlet的理解Servlet
- 關於-this指向的理解
- 關於DCI的理解
- 關於SAX,DOM,JAXP,JDOM,DOM4J的一些理解
- 關於storyboard開發的一些理解(從視訊上看的)
- Paxos演算法的通俗理解演算法
- 關於python中可迭代物件和迭代器的一些理解Python物件
- [spring][讀書筆記]一些關於依賴注入的理解。Spring筆記依賴注入
- 關於DDD概念的一些理解和困惑,煩勞Banq點撥
- es6關於class在js和ts中的的一些理解JS