用 NSCalendar 处理类似微博发帖时间并封装

服务器返回数据

服务器返回数据往往是一整串时间, 放在发帖时间label上面太长不好看, 我们需要手动处理一下使其变得美观易读.

代码

Date+Category 封装

需要处理服务器返回一大段时间, 我们需要比较现在时间和发帖时间
首先利用日期格式化类NSDateFormatter去格式化服务器返回的一长串时间字符串.

1
2
3
4
5
6
//日期格式化类
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//设置日期格式
dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

(...此处省略其他代码)

如果直接将以上代码放在cell里面读取会使cell里setModel方法显得冗长, 不美观, 我选择将它们封装起来. 为了便于其他人维护, 不再新建一类, 直接用date+category增加方法.
在date+category方法中自己写入方法:- (NSDateComponents *)zyn_deltaFromDateString:(NSString *)dateString withDateFormat:(NSString *)dateFormat;
然后实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
比较传入时间和现在时间的差值

@param dateString 获取的时间字符串
@param dateFormat 字符串时间格式

@return 差值
*/
- (NSDateComponents *)zyn_deltaFromDateString:(NSString *)dateString
withDateFormat:(NSString *)dateFormat {
//日期格式化类
NSDateFormatter *zyn_dateFormat = [[NSDateFormatter alloc] init];
//设置日期格式
zyn_dateFormat.dateFormat = dateFormat;

//创建时间
NSDate *create = [zyn_dateFormat dateFromString:dateString];

//日历
NSCalendar *zyn_calendar = [NSCalendar currentCalendar];

//比较时间
NSCalendarUnit zyn_unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
return [zyn_calendar components:zyn_unit fromDate:create toDate:self options:0];
}

时间判断

在求出时间差值以后, 需要自己对时间进行判断, 做条件的话, 封装BOOL方法比较适合, 需要做时间判断的个人认为只需要做今年以内的时间判断就好了, 之前的时间, 去年, 前年, 大前年, 这种完全没必要.

同样是在date类目中

今年?

1
2
3
4
5
6
7
8
9
10
11
12
13
- (BOOL)isCurrentYear {

//现在时间
NSDate *current = [NSDate date];

//日历
NSCalendar *calender = [NSCalendar currentCalendar];

NSInteger currentYear = [calender component:NSCalendarUnitYear fromDate:current];
NSInteger selfYear = [calender component:NSCalendarUnitYear fromDate:self];

return currentYear == selfYear;
}

今天?

1
2
3
4
5
6
7
8
9
10
11
12
- (BOOL)isToday {

NSDate *current = [NSDate date];

NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";

NSString *nowStr = [fmt stringFromDate:current];
NSString *selfStr = [fmt stringFromDate:self];

return [nowStr isEqualToString:selfStr];
}

昨天?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (BOOL)isYesterday {

NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"yyyy-MM-dd";

NSDate *currentDate = [fmt dateFromString:[fmt stringFromDate:[NSDate date]]];
NSDate *selfDate = [fmt dateFromString:[fmt stringFromDate:self]];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSDateComponents *cmps = [calendar components:unit fromDate:selfDate toDate:currentDate options:0];

return cmps.year == 0 && cmps.month == 0 && cmps.day == 1;
}

OK, 时间类目封装完毕, 需要在cell的label上显示时间了.
同样判断时间需要很长的代码, 写在cell上过于冗长, 影响美观, 既然label.text是字符串, 那么我们就在string+category中完成这些判断即可.


string+category封装

直接上代码了, 逻辑就不细说了, 反正先从大时间开始判断就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#import "NSString+ZYNExtension.h"

@implementation NSString (ZYNExtension)

- (NSString *)zyn_timeWithString:(NSString *)timeStr
andOriginalDateFormat:(NSString *)dateFormat
andYesterdayFormat:(NSString *)yFormat
andYearFormat:(NSString *)yearFormat {

// 日期格式化类
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
// 设置日期格式(y:年,M:月,d:日,H:时,m:分,s:秒)
fmt.dateFormat = dateFormat;
// 帖子的创建时间
NSDate *create = [fmt dateFromString:timeStr];

if (create.isCurrentYear) {
if (create.isToday) {

//取出时间组成
NSDateComponents *cmps = [[NSDate date] zyn_deltaFromDateString:timeStr withDateFormat:dateFormat];

if (cmps.hour >= 1) {

return [NSString stringWithFormat:@"%zd小时前", cmps.hour];

//大于一分钟还是大于半分钟还是大于几秒钟, 这个根据自己喜好再加判断就行
} else if (cmps.minute >= 1) {

return [NSString stringWithFormat:@"%zd分钟前", cmps.minute];

} else {

return @"刚刚";
}

} else if (create.isYesterday) {
//传入昨天需要的时间格式
fmt.dateFormat = yFormat;
return [fmt stringFromDate:create];

} else {

//传入今年其他时间需要的格式
fmt.dateFormat = yearFormat;
return [fmt stringFromDate:create];
}

} else {
return timeStr;
}
}
@end

String类目封装完事, 接下来就是在cell上显示了, model和cell中代码会非常简单


model和cell中的代码

在pch文件中引入上面的头文件

model中代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "ZYNHomeModel.h"

static NSString *const dateFormat = @"yyyy-MM-dd HH:mm:ss";

@implementation ZYNHomeModel

//重写网络获取的时间字符串get方法
- (NSString *)createTime {

return [[NSString string] zyn_timeWithString:_createTime
andOriginalDateFormat:dateFormat
andYesterdayFormat:@"昨天 HH:mm"
andYearFormat:@"MM-dd HH:mm"];
}

@end

cell中代码

在setModel方法中:
self.timeLabel.text = self.homeModel.createTime;
即可, 不用出现任何逻辑判断


效果

屏幕快照 2016-03-14 下午3.31.40

屏幕快照 2016-03-14 下午3.32.03