1. 程式人生 > >iOS學習筆記37-時間和日期計算

iOS學習筆記37-時間和日期計算

htm chinese 區域 nsis ios geo 代號 keyword 轉換

一、時間和日期計算

我們在應用開發中,時常須要和時間打交道,比方獲取當前時間,獲取兩個時間點相隔的時間等等,在iOS開發中與時間相關的類有例如以下幾個:
1. NSDate:表示一個絕對的時間點
2. NSTimeZone:時區信息
3. NSLocale:本地化信息
4. NSDateComponents:一個封裝了具體年月日、時秒分、周、季度等的類
5. NSCalendar:日歷類,它提供了大部分的日期計算接口
6. NSDateFormatter:用來在日期和字符串之間轉換

二、NSDate時間點

NSDate存儲的是世界標準時(UTC),輸出時須要依據時區轉換為本地時間

NSDate經常使用初始化方法:
/* 獲取當前時間,alloc/init得到的時間也是當前時間 */
+ (instancetype)date;
/* 以當前時間為基準,獲取偏移秒數的時間 */
+ (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds;
/* 以1970年1月1日為基準。獲取偏移秒數的時間 */
+ (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds;
/* 以2001年1月1日為基準。獲取偏移秒數的時間 */
+ (instancetype)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds;
/* 以指定時間點為基準。獲取偏移秒數的時間 *
/ + (instancetype)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date; /* 獲取一個極早的時間點,0001-12-30 00:00:00 +0000 */ + (instancetype)distantPast; /* 獲取一個極晚的時間點,4001-01-01 00:00:00 +0000 */ + (instancetype)distantFuture;
  • 除了最後的2個獲取極早極晚時間的方法,其他方法都有相應的init前綴方法。

  • 極早和極晚時間經常使用於定時器的開始和暫停
  • 偏移秒數為正。表示比基準時間晚的時間,偏移秒數為負,表示比基準時間早的時間
NSDate經常使用的對象方法:
/* 以當前NSDate對象為基準,獲取偏移指定秒數後得到的新NSDate對象 */
- (instancetype)dateByAddingTimeInterval:(NSTimeInterval)seconds;
#pragma mark - 比較2個時間
/* 比較2個NSDate對象,返回較早的那個NSDate時間點對象 */
- (NSDate *)earlierDate:(NSDate *)anotherDate;
/* 比較2個NSDate對象,返回較晚的那個NSDate時間點對象 */
- (NSDate *)laterDate:(NSDate *)anotherDate;
/* 比較2個NSDate對象。返回枚舉類型(相等、早於、晚於) */
- (NSComparisonResult)compare:(NSDate *)anotherDate;
#pragma mark - 獲取相隔秒數,從參數時間開始,經過多少秒到達對象運行時間
/* 返回當前對象時間與1970年1月1日00:00:00的相隔秒數 */
- (NSTimeInterval)timeIntervalSince1970;
/* 返回當前對象時間與2001年1月1日00:00:00的相隔秒數 */
- (NSTimeInterval)timeIntervalSinceReferenceDate;
/* 返回當前對象時間與當前client時間的相隔秒數 */
- (NSTimeInterval)timeIntervalSinceNow;
/* 返回當前對象時間與指定時間的相隔秒數 */
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;
以下是使用實例:
/* 獲取當前client時間 */
NSDate *date1 = [NSDate date];
/* 獲取比date1晚30秒的時間 */
NSDate *date2 = [NSDate dateWithTimeInterval:30 sinceDate:date1];
/* 比較2個時間,獲取較早的時間和較晚的時間 */
NSDate *earlierDate = [date1 earlierDate:date2];
NSDate *laterDate   = [date1 laterDate:date2];
NSLog(@"earlierDate:[email protected]:%@",earlierDate,laterDate);
/* 比較2個時間 */
NSComparisonResult result = [date1 compare:date2];
switch(result){
    case NSOrderedSame:
        NSLog(@"對象時間等於參數時間");
        break;
    case NSOrderedAscending:
        NSLog(@"對象時間早於參數時間");
        break;
    case NSOrderedDescending:
        NSLog(@"對象時間晚於參數時間");
        break;
}
/* 獲取相隔時間秒數,將返回結果-30,從date2的時間開始,倒退30秒到達date1的時間 */
NSTimeInterval seconds = [date1 timeIntervalSinceDate:date2];
NSLog(@"[email protected]",seconds);

三、NSTimeZone時區

NSTimeZone經常使用初始化方法:
/* 依據時區名稱初始化。比如:America/Chicago(美國芝加哥) */
+ (instancetype)timeZoneWithName:(NSString *)aTimeZoneName;
/* 依據時區縮寫初始化,比如:EST(美國東部標準時間)、HKT(香港標準時間) */
+ (instancetype)timeZoneWithAbbreviation:(NSString *)abbreviation;
/* 返回系統時區 */
+ (NSTimeZone *)systemTimeZone;
/* 返回本地時區 */
+ (NSTimeZone *)localTimeZone;
  • 時區名稱能夠通過以下方法獲取:
/* 以數組形式返回全部已知的時區名稱 */
+(NSArray *)knownTimeZoneNames;
  • 本地時區和系統時區的差別在於本地時區能夠被改動,而系統時區不能改動
NSTimeZone經常使用對象方法:
/* 獲取時區名稱 */
- (NSString *)name;
/* 獲取時區縮寫 */
- (NSString *)abbreviation;
/* 獲取對象時區與零時區的間隔秒數 */
- (NSInteger)secondsFromGMT;

四、NSLocale本地化信息

NSLocale類返回本地化信息。主要體如今語言區域格式這兩個設置項。

NSLocale經常使用初始化方法:
/* 返回系統初始本地化信息 */
+(instancetype)systemLocale;
/* 返回當前client的本地化信息。即使改動了本地化設定,這個對象也不會改變 */
+(instancetype)currentLocale;
/* 返回當前client的本地化信息,當每次改動本地化設定,事實上例化的對象會隨之改變 */
+(instancetype)autoupdatingCurrentLocale;
/* 用標示符初始化本地化信息。比如:en_US */
-(instancetype)initWithLocaleIdentifier:(NSString *)string;
NSLocale經常使用對象方法:
/* 依據不同的key返回各種本地化信息 */
- (id)objectForKey:(id)key;
/* 顯示特定地區代號下相應鍵的顯示名稱 */
- (NSString *)displayNameForKey:(id)key 
                          value:(id)value;
以下是使用實例:
//獲取系統本地化信息
NSLocale *sysLocale = [NSLocale systemLocale];
//獲取client本地化信息,不可響應改動
NSLocale *curLocale = [NSLocale currentLocale];
//獲取client本地化信息,可動態響應改動
NSLocale *autoCurLocale = [NSLocale autoupdatingCurrentLocale];
//通過標識創建自己定義本地化信息
NSLocale *userLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
//獲取貨幣符號
NSString *strSymbol = [userLocale objectForKey:NSLocaleCurrencySymbol];
NSLog(@"貨幣符號:%@",strSymbol);//打印:¥
//獲取本地日歷
NSCalendar *calendar = [userLocale objectForKey:NSLocaleCalendar];
NSLog(@"本地日歷:%@",calendar);
//得到"en_US"的NSLocaleIdentifier鍵的顯示名稱
NSString *str = [userLocale displayNameForKey:NSLocaleIdentifier value:@"en_US"];
NSLog(@"標識顯示名稱:%@",str);//打印:英文(美國)

五、NSDateComponents時間封裝

NSDateComponents封裝了具體年月日、時秒分、周、季度等:

/* 創建一個日期對象 */
NSDateComponents*compt = [[NSDateComponents alloc] init];
[compt setEra:1];//紀元
[compt setYear:2013];//年
[compt setMonth:3];//月
[compt setDay:15];//日
[compt setHour:11];//小時
[compt setMinute:20];//分鐘
[compt setSecond:55];//秒鐘
[compt setQuarter:2];//幾刻鐘
[compt setTimeZone:[NSTimeZone systemTimeZone]];//時區
[compt setWeek:3];//一年的第幾周
[compt setWeekday:4];//周幾
[compt setWeekOfMonth:3];//一個月的第幾周
[compt setWeekOfYear:3];//一年的第幾周
[compt setCalendar:[NSCalendar currentCalendar]];//日歷

NSDateComponents通常不單獨使用。它經常與時間點NSDate、日歷類NSCalendar一起使用

六、NSCalendar日歷類

NSCalendar類,表示日歷,封裝了大量的計算日期方法

NSCalendar經常使用創建方法:
/* 返回client的邏輯日歷,即使改動了系統日歷設定,這個對象也不會改變 */
+(instancetype)currentCalendar;
/* 返回client的邏輯日歷,改動了系統日歷設定。這個對象會隨之改變 */
+(instancetype)autoupdatingCurrentCalendar;
/* 依據提供的日歷標示符初始化 */
-(instancetype)initWithCalendarIdentifier:(NSString *)string;
系統中定義的日歷標識符有:
  • NSGregorianCalendar:公歷
  • NSBuddhistCalendar:佛教日歷
  • NSChineseCalendar:中國農歷
  • NSHebrewCalendar:希伯來日歷
  • NSIslamicCalendar:伊斯蘭歷
  • NSIslamicCivilCalendar:伊斯蘭教日歷
  • NSJapaneseCalendar:日本日歷
  • NSRepublicOfChinaCalendar:中華民國日歷(臺灣)
  • NSPersianCalendar:波斯歷
  • NSIndianCalendar:印度日歷
  • NSISO8601Calendar:ISO8601日歷
NSCalendar經常使用的與NSDateComponents相關對象方法:
/* 
  取得一個NSDate對象的1個或多個部分轉為NSDateComponents,
  僅僅有明白指定了unitFlags。NSDateComponents相應的那一部分才有值
 */
- (NSDateComponents *)components:(NSUInteger)unitFlags 
                        fromDate:(NSDate *)date;
/* 取得兩個NSDate對象的時間間隔,用NSDateComponents來封裝 */
- (NSDateComponents *)components:(NSUInteger)unitFlags 
                        fromDate:(NSDate *)startingDate 
                          toDate:(NSDate*)resultDate 
                         options:(NSUInteger)opts;/* 一般默認傳0就可以 */
/* 依據NSDateComponents對象得到一個NSDate對象 */
- (NSDate *)dateFromComponents:(NSDateComponents *)comps;
/* 在參數date基礎上,添加一個NSDateComponents類型的時間增量 */
- (NSDate *)dateByAddingComponents:(NSDateComponents *)comps 
                            toDate:(NSDate *)date 
                           options:(NSUInteger)opts;/* 一般默認傳0就可以 */

unitFlags參數通過以下的日歷單位NSCalendarUnit用或運算“|”組合使用

日歷單位NSCalendarUnit,能夠用或運算“|”組合使用:
  • NSEraCalendarUnit
    紀元單位。對於NSGregorianCalendar(公歷)來說,僅僅有公元前(BC)和公元(AD)。而對於其他歷法可能有非常多,比如日本和歷是以每一代君王統治來做計算。
  • NSYearCalendarUnit:年單位。值非常大,相當於經歷了多少年,未來多少年。

  • NSMonthCalendarUnit:月單位。

    範圍為1-12

  • NSDayCalendarUnit:天單位。

    範圍為1-31

  • NSHourCalendarUnit:小時單位。範圍為0-24
  • NSMinuteCalendarUnit:分鐘單位。

    範圍為0-60

  • NSSecondCalendarUnit:秒單位。範圍為0-60
  • NSWeekCalendarUnit:周單位。範圍為1-53
  • NSWeekdayCalendarUnit:星期單位。每周的7天。範圍為1-7
  • NSWeekdayOrdinalCalendarUnit:沒全然搞清楚
  • NSQuarterCalendarUnit:幾刻鐘,也就是15分鐘。範圍為1-4
  • NSWeekOfMonthCalendarUnit:月包括的周數。最多為6個周
  • NSWeekOfYearCalendarUnit:年包括的周數。

    最多為53個周

  • NSYearForWeekOfYearCalendarUnit:沒全然搞清楚
  • NSTimeZoneCalendarUnit:沒全然搞清楚
以下是使用實例:
//獲取client邏輯日歷
NSCalendar *calendar = [NSCalendar currentCalendar];
//獲取當前時間
NSDate *date = [NSDate date];
//從date中讀取年月日。存儲在NSDateComponents對象中
NSDateComponents *compt1 = [calendar components:(NSYearCalendarUnit | 
                                                 NSMonthCalendarUnit | 
                                                 NSDayCalendarUnit) 
                                       fromDate:date];

NSLog(@"年:%d",[compt1 year]);//2016
NSLog(@"月:%d",[compt1 month]);//4
NSLog(@"日:%d",[compt1 day]);//19
/*********************************************************************/
//創建一個時間相差5小時1分15秒的時間點
NSDate *date2 = [NSDate dateWithTimeInterval:5*60*60+1*60+15 
                                   sinceDate:date];
//時間間隔NSDate轉NSDateComponents,分鐘加秒鐘
NSDateComponents *compt2 = [calendar components:(NSMinuteCalendarUnit | 
                                                 NSSecondCalendarUnit) 
                                       fromDate:date 
                                         toDate:date2 
                                        options:0];

NSLog(@"時間間隔【分種加秒鐘】:%d分%d秒",[compt2 minute],[compt2 second]);//301分15秒
//時間間隔NSDate轉NSDateComponents,僅僅有秒鐘
NSDateComponents *compt3 = [calendar components:NSSecondCalendarUnit
                                       fromDate:date 
                                         toDate:date2 
                                        options:0];
NSLog(@"時間間隔【秒數】:%d秒",[compt3 second]);//18075秒
/*********************************************************************/
//創建自己定義NSDateComponents對象
NSDateComponents *compt4 = [[NSDateComponents alloc] init];
[compt4 setYear:2012];
[compt4 setMonth:5];
[compt4 setDay:11];
//NSDateComponents對象轉NSDate對象
NSDate *newDate = [calendar dateFromComponents:compt4];
//得到本地時間,避免時區問題
NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSInteger interval = [zone secondsFromGMTForDate:newDate];
NSDate *localeDate = [newDate dateByAddingTimeInterval:interval];
NSLog(@"NSDateComponents對象轉NSDate對象:%@",localeDate);
/*********************************************************************/
//創建自己定義NSDateComponents對象
NSDateComponents *compt5 = [[NSDateComponents alloc] init];
[compt5 setDay:25];
[compt5 setHour:4];
[compt5 setMinute:66];
NSDate *addDate = [calendar dateByAddingComponents:compt5 
                                            toDate:[NSDate date] 
                                           options:0];
//得到本地時間。避免時區問題
NSTimeZone *zone2 = [NSTimeZone systemTimeZone];
NSInteger interval2 = [zone2 secondsFromGMTForDate:addDate];
NSDate *localeDate2 = [addDate dateByAddingTimeInterval:interval2];
NSLog(@"NSDate對象追加NSDateComponents對象時間:%@",localeDate2);
NSCalendar類另一些日歷設置和計算的方法:
/* 設置本地化信息 */
- (void)setLocale:(NSLocale *)locale;
/* 設置時區信息 */
- (void)setTimeZone:(NSTimeZone *)tz;
/* 設置每周的第一天是從星期幾開始,1表示是星期天(默認)。2表示星期一。以此類推 */
- (void)setFirstWeekday:(NSUInteger)weekday;
/* 設置每年及每月第一周必須包括的最少天數,比方:設定第一周最少包括3天。則value傳入3 */
- (void)setMinimumDaysInFirstWeek:(NSUInteger)value;
/* 獲取一個小的單位在一個大的單位裏面的序數 */
- (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller 
                        inUnit:(NSCalendarUnit)larger 
                       forDate:(NSDate *)date;
/* 依據參數提供的時間點。得到一個小的單位在一個大的單位裏面的取值範圍 */
- (NSRange)rangeOfUnit:(NSCalendarUnit)smaller 
                inUnit:(NSCalendarUnit)larger 
               forDate:(NSDate *)date;
/* 
  依據參數提供的時間點,返回所在日歷單位的開始時間。

假設startDate和interval都計算得出來。則返回YES。否則返回NO */ - (BOOL)rangeOfUnit:(NSCalendarUnit)unit /* 日歷單位 */ startDate:(NSDate **)datep /* 開始時間。通過參數返回 */ interval:(NSTimeInterval *)tip /* 日歷單位所相應的秒數。通過參數返回 */ forDate:(NSDate *)date; /* 時間點參數 */

七、NSDateFormatter字符串格式化

NSDateFormatter專門負責時間NSDate和字符串NSString之間的轉換

以下是格式化符使用規定:
  • 大寫G:紀元
    通常會顯示公元前(BC)和公元(AD)
  • 小寫y:年
    假如是2013年。那麽yyyy=2013,yy=13
  • 大寫M:月
    假如是3月,那麽M=3,MM=03,MMM=Mar,MMMM=March
    假如是11月,那麽M=11。MM=11。MMM=Nov。MMMM=November
  • 小寫w:年包括的周
    假如是1月8日。那麽w=2(這一年的第二個周)
  • 大寫W:月份包括的周(與日歷排列有關)
    假如是2013年4月21日。那麽W=4(這個月的第四個周)
  • 大寫F:月份包括的周(與日歷排列無關)
    和上面的W不一樣,F僅僅是單純以7天為一個單位來統計周。比如7號一定是第一個周。15號一定是第三個周,與日歷排列無關。

  • 大寫D:年包括的天數
    假如是1月20日。那麽D=20(這一年的第20天)
    假如是2月25日,那麽D=31+25=56(這一年的第56天)
  • 小寫d:月份包括的天數
    假如是5號。那麽d=5。dd=05
    假如是15號,那麽d=15,dd=15
  • 大寫E:星期
    假如是星期五,那麽E=Fri。EEEE=Friday
  • 小寫a:上午(AM)/下午(PM)
  • 大寫H:24小時制。顯示為0–23
    假如是午夜00:40,那麽H=0:40,HH=00:40
  • 小寫h:12小時制,顯示為1–12
    假如是午夜00:40,那麽h=12:40
  • 大寫K:12小時制,顯示為0–11
    假如是午夜00:40。那麽K=0:40,KK=00:40
  • 小寫k:24小時制,顯示為1–24
    假如是午夜00:40。那麽k=24:40
  • 小寫m:分鐘
    假如是5分鐘。那麽m=5,mm=05
    假如是45分鐘。那麽m=45。mm=45
  • 小寫s:秒
    假如是5秒鐘。那麽s=5。ss=05
    假如是45秒鐘,那麽s=45。ss=45
  • 大寫S:毫秒
    一般用SSS來顯示
  • 小寫z:時區
    表現形式為GMT+08:00
  • 大寫Z:時區
    表現形式為+0800
以下是使用範例:
//創建日期字符串格式化器
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//設置時區
[formatter setTimeZone:[NSTimeZone systemTimeZone]];
//設置格式化輸出格式
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
//創建時間
NSDateComponents *compt = [[NSDateComponents alloc] init];
[compt setYear:2013];
[compt setMonth:3];
[compt setDay:13];
[compt setHour:1];
[compt setMinute:55];
[compt setSecond:28];
//獲取日歷對象
NSCalendar *calendar = [NSCalendar currentCalendar];
//設置時區
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
//NSDateComponents對象轉NSDate對象
NSDate *date = [calendar dateFromComponents:compt];
NSLog(@"date:%@",date);
//格式化輸出字符串,傳入要格式化的時間NSDate對象
NSString *str = [formatter stringFromDate:date];
NSLog(@"格式化輸出:%@",str);
具體介紹能夠參考這裏。講得非常具體:wayne23的博客
假設有什麽問題能夠在下方評論區中提出。O(∩_∩)O哈!

iOS學習筆記37-時間和日期計算