對類似於微博發布時間這種樣式的時間日期轉換,做了如下整理與總結,總得來說解決了這麼幾個關鍵性的問題:
(1)對伺服器端返回的時間日期文字進行本地化設定(伺服器返回的可能不是中國地區的時間格式。如返回歐美時間格式。)
(2)自訂時間日期格式,返回符合自訂格式的字串
(3)如何判定一個NSDate對象的是否為今年/今天/昨天(為NSDate提供一個分類,對三種判定分別提供兩種版本下的判斷。 iOS 所有版本均適用/ iOS 8 以後的版本適用)
相關代碼:
(1)處理字串格式部分
/** * 類別 格式 * (1)今年 * ①今天 * a.一分鐘內 剛剛 * b.1分鐘~59分鐘之間 xx分鐘前 * c.大於等於60分鐘 xx小時前 * ②昨天 昨天 xx:xx (時:分) * ③今年的其他日子 xx-xx * * (2)非今年 xxxx-xx-xx *//** * preTimerStr == Thu Oct 16 17:06:25 +0800 2014 (伺服器返回的時間日期文字) * dateFormat == EEE MMM dd HH:mm:ss Z yyyy (歐美時間原本的格式) * E:星期幾(這些屬性都是有幾位寫幾位) * M:月份 * d:幾號(這個月的第幾天) * H:24小時制的小時 * m:分鐘 * s:秒 * Z:時區位移量 * y:年 */// 傳入一個timeStr,返回對應格式的字串- (NSString *)setupCreateTime:(NSString *)timeStr { // NSDateFormatter:NSString與NSDate互轉 NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; /* // 如果我們得到的是其他地區時間格式,需要設定locale(我們獲得的一開始是歐美時間,所以說這裡寫 en_US) fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; // 設定日期格式(聲明字串裡面每個數字和單詞的含義) fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; // 因為我們直接獲得到的_created_at是歐美時間(NSString類型,無法直接使用),所以要先用歐美格式將我們獲得到的字串轉化為NSDate,然後再設定一次格式,將NSDate轉化成為字串格式 // 微博的建立日期(將_created_at字串對象轉化成為NSDate對象) NSDate *createDateUS = [fmt dateFromString:timeStr]; // 此時 // 再次設定日期格式(然後再通過這個日期格式去處理時間字串) fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss"; */ // 設定格式 fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss"; // 發布日期對象 NSDate *createDate = [fmt dateFromString:timeStr]; // 處理時間(用文章發布時間與目前時間比較) // 判斷是否是今年 年份是否相等 => 擷取日期年份 => 日曆,擷取日期組件 // 擷取文章發布時間與目前時間差值 NSCalendar *calendar = [NSCalendar currentCalendar]; // 擷取兩個日期差值 NSDateComponents *cmp = [calendar components:NSCalendarUnitHour | NSCalendarUnitMinute fromDate:createDate toDate:[NSDate date] options:NSCalendarWrapComponents]; if ([createDate isThisYear]) { if ([createDate isThisToday]) { // 擷取日期差值 if (cmp.hour >= 1) { timeStr = [NSString stringWithFormat:@"%ld小時前",cmp.hour]; } else if (cmp.minute >= 2) { timeStr = [NSString stringWithFormat:@"%ld分鐘前",cmp.minute]; } else { // 剛剛 timeStr = @"剛剛"; } } else if ([createDate isThisYesterday]) { // 昨天 // 昨天 21:10 fmt.dateFormat = @"昨天 HH:mm"; timeStr = [fmt stringFromDate:createDate]; } else { // 今年的其他日子 fmt.dateFormat = @"MM-dd"; timeStr = [fmt stringFromDate:createDate]; } } else { // 非今年 fmt.dateFormat = @"yyyy-MM-dd"; timeStr = [fmt stringFromDate:createDate]; } return timeStr;}
(2) NSDate+Date 部分
//// NSDate+Date.h// WZYBaiSi//// Created by 王中堯 on 16/8/7.// Copyright © 2016年 wzy. All rights reserved.//#import <Foundation/Foundation.h>@interface NSDate (Date)// 是否是今年- (BOOL)isThisYear;// 是否今天- (BOOL)isThisToday;// 是否昨天- (BOOL)isThisYesterday;@end
//// NSDate+Date.m// WZYBaiSi//// Created by 王中堯 on 16/8/7.// Copyright © 2016年 wzy. All rights reserved.//#import "NSDate+Date.h"@implementation NSDate (Date)// 判斷是否為今年- (BOOL)isThisYear{ // 日曆對象(方便比較兩個日期之間的差距) NSCalendar *calendar = [NSCalendar currentCalendar]; // NSCalendarUnit枚舉代表想獲得哪些差值(這裡設定年月日時分秒,那麼接下來差值就會顯示這幾項的資訊) // NSCalendarUnit unit = NSCalendarUnitYear; // 這裡直接放在下面就好了,不用再聲明一個NSCalendarUnit對象 // 獲得某個時間的“年”這個元素 NSDateComponents *dateCmps = [calendar components:NSCalendarUnitYear fromDate:self]; // 傳進來的建立時間 NSDateComponents *nowCmps = [calendar components:NSCalendarUnitYear fromDate:[NSDate date]]; //目前時間 return dateCmps.year == nowCmps.year;}// 判斷是否是今天- (BOOL)isThisToday{ NSDate *nowDate = [NSDate date]; NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; // 先將這兩個NSDate對象轉換成NSString對象 NSString *dateStr = [fmt stringFromDate:self]; NSString *nowStr = [fmt stringFromDate:nowDate]; // 將不含時分秒的date字串相比較,年月日完全相同時自然是同一天,也就是今天了 return [dateStr isEqualToString:nowStr]; }// 判斷是否是昨天- (BOOL)isThisYesterday{ NSDate *nowDate = [NSDate date]; NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"yyyy-MM-dd"; // 先將這兩個NSDate對象轉換成NSString對象 NSString *dateStr = [fmt stringFromDate:self]; NSString *nowStr = [fmt stringFromDate:nowDate]; // 再將NSString按照fmt格式轉換成不含 時分秒 的NSDate格式(目的就是為了去除 時分秒,單純比較年月日) NSDate *date = [fmt dateFromString:dateStr]; nowDate = [fmt dateFromString:nowStr]; // 日曆對象(方便比較兩個日期之間的差距) NSCalendar *calendar = [NSCalendar currentCalendar]; NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay; NSDateComponents *cmps = [calendar components:unit fromDate:date toDate:nowDate options:0]; // 我們只判斷year與month相同情況下的day。year不同那麼就算是昨天是去年的最後一天,我們也按照“非今年”的格式顯示。month不同那麼就算是昨天是上個月的最後一天我們也按照“今年的其他日子”的格式顯示 return cmps.year == 0 && cmps.month == 0 && cmps.day == 1;}// 另外提供一種比較簡便的寫法,但只適用於 iOS 8 以後/*NS_AVAILABLE宏告訴我們這方法分別隨Mac OS 10.9和iOS 8.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)isThisYear{ // 擷取當前日期對象 NSDate *curDate = [NSDate date]; // 擷取日曆類 NSCalendar *curCalendar = [NSCalendar currentCalendar]; // 擷取自己日期組件(年,月,等) NSDateComponents *selfCmp = [curCalendar components:NSCalendarUnitYear fromDate:self]; // 擷取目前時間日期組件(年,月,等) NSDateComponents *curCmp = [curCalendar components:NSCalendarUnitYear fromDate:curDate]; return curCmp.year == selfCmp.year;}// 判斷是否是今天- (BOOL)isThisToday{ // 擷取日曆類 NSCalendar *curCalendar = [NSCalendar currentCalendar]; return [curCalendar isDateInToday:self];}- (BOOL)isThisYesterday{ NSCalendar *curCalendar = [NSCalendar currentCalendar]; return [curCalendar isDateInYesterday:self];}*/@end