iOS之時間相關(guān)

在iOS中,我們處理時間的時候,往往會使用到NSDate這個類,但是有的時候我們或許也會使用到NSCalendar這個類,下面就先簡單介紹下NSDate這個類。

NSDate和字符串的相互轉(zhuǎn)換

1.將字符串轉(zhuǎn)為帶格式的日期

  • 字符串有規(guī)則的樣式
void string2date() {
    // 時間字符串
    NSString *string = @"2015-11-20 09:33:22";
    // 日期格式化類
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 設(shè)置日期格式(為了轉(zhuǎn)換成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    NSString *newStr = [fmt stringFromDate:date];
    NSLog(@"%@", date);
    NSLog(@"%@", newStr);
}
// 打印結(jié)果
2016-10-20 01:33:22 +0000
2016-10-20 09:33:22

可以看出以上的打印結(jié)果是有八個小時的時差,這是由于上面的date所表示的區(qū)域是格林威治時間,我們處于的是東八區(qū)。

  • 字符串的樣式不規(guī)則

以上的字符串是有著比較規(guī)則的樣式,假如有的服務(wù)器返回的結(jié)果是比較混亂的話,在對日期的格式樣式重新設(shè)置的話也是可以得到的想要的數(shù)據(jù)。

void string2date2() {
    // 時間字符串
    NSString *string = @"10月-20號/2016年 09-10:05秒";
    // 日期格式化類
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"MM月-dd號/yyyy年 HH-mm:ss秒";
    NSLog(@"%@", [fmt dateFromString:string]);
}
// 打印結(jié)果
2016-10-20 01:10:05 +0000
  • 當(dāng)字符串中有英文的表達(dá)樣式
void string2date3() {
    // 時間字符串
    NSString *string = @"Tue May 31 17:46:55 +0800 2011";
    // 日期格式化類
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
    // fmt.dateFormat = @"EEE MMM dd HH:mm:ss ZZZZ yyyy";
    // 設(shè)置語言區(qū)域(因為這種時間是歐美常用時間)
    fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
    NSLog(@"%@", [fmt dateFromString:string]);
}
// 打印結(jié)果
2016-05-31 09:46:55 +0000

上面的代碼中的EEE表示的是星期的縮寫,MMM表示的月份的縮寫,其中的ZZZZZ表示的是時區(qū)。

  • 時間戳樣式

有時候服務(wù)器返回我們的字符串不一定是以上的規(guī)則的樣式或者是不規(guī)則樣式的字符串,返回給我們就是一長串的數(shù)字,這就是時間戳,其意思是距離1970年1月1日0點(diǎn)0分0秒的時間,單位是

void string2date4() {
    // 時間戳 : 從1970年1月1號 00:00:00開始走過的秒數(shù)
    // 時間字符串 - 時間戳
    NSString *string = @"1745645645645";
    // 轉(zhuǎn)為秒為單位
    NSTimeInterval second = string.longLongValue / 1000.0;
    // 時間戳 -> NSDate *
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:second];  
    NSLog(@"%@", date);
}
// 打印結(jié)果
2025-04-26 05:34:05 +0000

2.日期轉(zhuǎn)為字符串

  • 轉(zhuǎn)為有固定格式的字符串
void date2string() {
    // 獲取當(dāng)前的時間
    NSDate *date = [NSDate date];
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 給轉(zhuǎn)換的字符串一個固定格式
    fmt.dateFormat = @"yyyy年MM月dd號 HH:mm:ss";
    NSString *string = [fmt stringFromDate:date];
    NSLog(@"----%@+++++", string);  
}
// 打印結(jié)果
----2016年10月24號 16:19:42+++++

在以上的代碼中需要特別值得注意的是給字符串一個固定的格式,不然轉(zhuǎn)換成的字符串就不知道以何種格式展示出來,打印出來為空。

獲取到日期的年月日時分秒

有的時候我們其實只需要獲取到時間中的年月日等元素,這時候就需要抽取時間元素中一些子元素。
如果返回的字符串的格式是規(guī)則的話就可以用定位的方式就可以截取到其中想要的元素。

void getComponentsOfDate() {
    // 時間字符串
    NSString *string = @"2016-10-20 09:10:05";
    NSString *month = [string substringWithRange:NSMakeRange(5, 2)];
    NSLog(@"%@", month);
}
// 打印結(jié)果
10

這樣是可以截取到想要的結(jié)果,但是如果我想得到時間中所有的元素,就要重復(fù)多次這樣的代碼,這樣就比較麻煩,所以不建議使用。我們可以考慮使用NSCalendar這個類中的方法去截取時間中的所有元素。

void getComponentsOfDate2() {
    // 時間字符串
    NSString *string = @"2016-10-20 09:10:05";
    // 日期格式化類
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 設(shè)置日期格式(為了轉(zhuǎn)換成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    // 利用NSCalendar處理日期
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSInteger month = [calendar component:NSCalendarUnitMonth fromDate:date];
    NSInteger hour = [calendar component:NSCalendarUnitHour fromDate:date];
    NSInteger minute = [calendar component:NSCalendarUnitMinute fromDate:date];
    NSLog(@"%zd %zd %zd", month, hour, minute);
}
// 打印結(jié)果
10 09 10

假如要一次性得到時間中的所有元素就可以考慮使用NSCalendarUnit類去得到時間中年月日等元素,這些都是可以用或運(yùn)算進(jìn)行操作的。

void getComponentsOfDate3() {
    // 時間字符串
    NSString *string = @"2016-10-20 09:10:05";
    // 日期格式化類
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    // 設(shè)置日期格式(為了轉(zhuǎn)換成功)
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    // NSString * -> NSDate *
    NSDate *date = [fmt dateFromString:string];
    // 利用NSCalendar處理日期
    NSCalendar *calendar = [NSCalendar currentCalendar];
    
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *cmps = [calendar components:unit  fromDate:date];
    //    NSLog(@"%zd %zd %zd", cmps.year, cmps.month, cmps.day);
    NSLog(@"%@", cmps);
}
// 打印結(jié)果
<NSDateComponents: 0x101018c10>
    Calendar Year: 2016
    Month: 10
    Leap month: no
    Day: 20
    Hour: 9
    Minute: 10
    Second: 5

通過以上的unit可以取到想要的元素,放到NSDateComponents中打印出來。

時間的比較

往往有的時候會用到時間與時間的相互比較,例如微博中,一條微博的發(fā)布,會顯示是什么時候發(fā)布的,如:“剛剛”、“一個小時前”等,這需要用到發(fā)布時間和當(dāng)前時間的比較,并且通過一系列的判斷展示到界面上去。

  • 簡單比較
void dateCompare() {
    // 時間字符串
    NSString *createdAtString = @"2015-11-20 11:10:05";
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];

    // 手機(jī)當(dāng)前時間
    NSDate *nowDate = [NSDate date];

    /**
     NSComparisonResult的取值
     NSOrderedAscending = -1L, // 升序, 越往右邊越大
     NSOrderedSame,  // 相等
     NSOrderedDescending // 降序, 越往右邊越小
     */
    // 獲得比較結(jié)果(誰大誰小)
    NSComparisonResult result = [nowDate compare:createdAtDate];
    if (result == NSOrderedAscending) { // 升序, 越往右邊越大
        NSLog(@"createdAtDate > nowDate");
    } else if (result == NSOrderedDescending) { // 降序, 越往右邊越小
        NSLog(@"createdAtDate < nowDate");
    } else {
        NSLog(@"createdAtDate == nowDate");
    }
}
// 打印結(jié)果
createdAtDate < nowDate

以上只能比較出兩個日期之前的先后或者是否為同一個時間,但是不能真實的比較出兩個時間之間相差的時間;

  • 間隔時間
void dateCompare2() {
    // 時間字符串
    NSString *createdAtString = @"2016-11-20 09:10:05";
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];

    // 手機(jī)當(dāng)前時間
    //    NSDate *nowDate = [NSDate date];

    // 獲得createdAtDate和nowDate的時間間隔(間隔多少秒)
    //    NSTimeInterval interval = [nowDate timeIntervalSinceDate:createdAtDate];
    NSTimeInterval interval = [createdAtDate timeIntervalSinceNow];
    NSLog(@"%f", interval);
}
// 打印結(jié)果
2305313.187479 
// 正表示當(dāng)前時間之后的時間,負(fù)表示當(dāng)前時間之前的時間。

timeIntervalSinceDate:表示一個時間到另一個時間的相隔的時間;
timeIntervalSinceNow表示的是一個時間到現(xiàn)在時間之間相隔的時間。

  • 高級比較

以上的結(jié)果是可以得到兩個相比較的時間之間的間隔時間,但是并不能很好的反應(yīng)出到底是相差多少天或者是多少個月,可以借助到NSCalendar中的一些方法可以解決上述的問題。

void dateCompare3() {
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";

    // 時間字符串
    NSString *createdAtString = @"2015-11-01 09:10:05";
    NSDate *createdAtDate = [fmt dateFromString:createdAtString];
    // 其他時間
    NSString *otherString = @"2015-10-31 08:56:45";
    NSDate *otherDate = [fmt dateFromString:otherString];
    // 獲得NSCalendar
    NSCalendar *calendar = nil;
    // 這個判斷主要是由于iOS版本的限制,`calendarWithIdentifier: `這個方法是iOS8.0之后開始使用的
    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
        calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
    } else {
        calendar = [NSCalendar currentCalendar];
    }

    // 獲得日期之間的間隔
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *cmps = [calendar components:unit fromDate:createdAtDate toDate:otherDate options:0];  
    NSLog(@"%@", cmps);
}
// 打印結(jié)果
<NSDateComponents: 0x10060a5e0>
    Calendar Year: 0
    Month: 0
    Day: -1
    Hour: 0
    Minute: -13
    Second: -20

從打印的結(jié)果可以清楚的看出兩個時間之間的相差多少日、時、分、秒等。

判斷是否為今天、昨天等

有的時候需要判斷當(dāng)前的日期是否今天或者是在當(dāng)月等的需求,這就需要作出判斷。

系統(tǒng)方法

void judgeToday() {
    // 獲得NSCalendar
    NSCalendar *calendar = nil;
    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
        calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
    } else {
        calendar = [NSCalendar currentCalendar];
    }    
    NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
    fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSLog(@"%zd", [calendar isDateInToday:[fmt dateFromString:@"2015-11-10 01:09:56"]]);  
}

以上的打印結(jié)果為0,所以得知不是今天;

// 今天的判斷
- (BOOL)isDateInToday:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 昨天的判斷
- (BOOL)isDateInYesterday:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 明天的判斷
- (BOOL)isDateInTomorrow:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 周末的判斷
- (BOOL)isDateInWeekend:(NSDate *)date NS_AVAILABLE(10_9, 8_0);
// 是否為同一天
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 NS_AVAILABLE(10_9, 8_0);

可以看出上面的代碼都是iOS8.0之后出現(xiàn)的,所以在iOS8.0之前的版本是適用不了的,如果想要得到判斷的話就需要自己去封裝,其中還是需要用到NSCalendar這個類,因為這個類可以取到時間中的所有元素。

自定義封裝

  • 判斷今天
- (BOOL)isToday {
    // 判斷self這個日期是否為今天
    NSCalendar *calendar = [NSCalendar calendar];  
    // 獲得年月日元素
    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
    // 獲取到self這個日期中所有的元素
    NSDateComponents *selfCmps = [calendar components:unit fromDate:self];
     // 獲取到`現(xiàn)在`這個日期中的所有元素
    NSDateComponents *nowCmps = [calendar components:unit fromDate:[NSDate date]];
    return selfCmps.year == nowCmps.year
    && selfCmps.month == nowCmps.month
    && selfCmps.day == nowCmps.day;
}
  • 判斷昨天或是明天
NSDateComponents *cmps = [calendar components:unit fromDate:selfDate toDate:nowDate options:0];
return cmps.year == 0
    && cmps.month == 0
    // 1代表昨天,-1代表明天(具體的還是要看具體代碼的邏輯)
    && cmps.day == -1;// 1

總結(jié):
1.在NSDate這個類中可以對字符串轉(zhuǎn)換成date數(shù)據(jù),對轉(zhuǎn)換成的字符串的格式是有要求的。
2.時間戳的處理,要看清楚服務(wù)器返回的字符串的位數(shù),要仔細(xì)處理時間戳的單位。
3.NSCalendar這個類中可以對時間的處理有些比較高端的處理,有些功能是NSDate處理不了的。但是如果在iOS 8.0之前,有些用法是需要自定義封裝的。
4.寫的不對的地方,還望大家直接指出,小弟不勝感激。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容