Hello, World!

时间与日期(下)

字数统计: 1.8k阅读时长: 7 min
2017/04/08 Share

NSDateComponents

NSDateComponents类的作用是把日期拆分成一个一个的组件。一个日期是由年月日时分秒组成的,该类可以把日期拆分成单独的年、月、日、时、分、秒。通常是和NSCalendar类一起使用。

初始化方法

  • - (instancetype)init

默认的初始化方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 创建NSDateComponents对象,设置时间点
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setEra:1]; // 时代
[components setYear:2017];
[components setMonth:3];
[components setDay:25];
[components setHour:11];
[components setMinute:20];
[components setSecond:55];
[components setQuarter:2]; // 季度
[components setWeekday:1]; // 星期 Sunday:1, Monday:2, Tuesday:3, Wednesday:4, Friday:5, Saturday:6
[components setWeekOfMonth:3]; // 当月的第几个星期
[components setWeekOfYear:2]; // 当年的第几个星期
[components setTimeZone:[NSTimeZone systemTimeZone]];
[components setCalendar:[NSCalendar currentCalendar]];

用法一

获取一个绝对的时间点对象

1
2
3
4
5
6
7
8
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setDay:6];
[dateComponents setMonth:5];
[dateComponents setYear:2017];

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [calendar dateFromComponents:dateComponents];
NSLog(@"%@", date);

log信息如下:
2017-05-06 00:00:00 +0000

用法二

在date基础上,增加一个NSDateComponents类型的时间增量

1
2
3
4
5
6
7
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setDay:3];

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *date = [calendar dateByAddingComponents:dateComponents toDate:[NSDate date] options:0];

NSLog(@"%@", date);

如果现在的时间是:2017-03-26 02:21:08 +0000
那么打印结果就是:2017-03-29 02:21:08 +0000

在当前时间基础上增加3天。不过这是格林尼治时区的时间,可以转化为当前东8区的时间

1
2
3
4
5
NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSInteger interval = [zone secondsFromGMTForDate:date]; // 当前时区和标准时区相差的秒数

NSDate *localeDate = [date dateByAddingTimeInterval:interval];
NSLog(@"%@", localeDate);

常用方法

下面这些方法都是属于NSCalendar类的,都返回一个NSDateComponents类。

  • - (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)date;

取得一个NSDate对象的1个或多个部分,结果用NSDateComponents来封装

1
2
3
4
5
6
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
NSLog(@"%zd", [components year]);
NSLog(@"%zd", [components month]);
NSLog(@"%zd", [components day]);
NSLog(@"%zd", [components weekday]);

需要注意的是,只有明确指定了unitFlags,NSDateComponents相应的那部分才有值。

年、月、日可以正常取到值,weekday则取不到正常值。

  • - (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate )startingDate toDate:(NSDate \)resultDate options:(NSCalendarOptions)opts;

取得两个NSDate对象的时间间隔,结果用NSDateComponents来封装

1
2
3
4
5
6
7
8
9
NSDate *date1 = [NSDate date];
NSDate *date2 = [NSDate dateWithTimeInterval:24*60*60+15 sinceDate:date1];

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSCalendarUnitDay|NSCalendarUnitSecond fromDate:date1 toDate:date2 options:0];

NSLog(@"%zd",[components year]);
NSLog(@"%zd",[components day]);
NSLog(@"%zd",[components second]);

day、second可以正常取到值,year则取不到正常值。

注意:

1)得到的NSDateComponents对象可能会包含负数。例如:当toDate比fromDate晚10秒,second部分返回10;当toDate比fromDate早10秒,second部分返回-10

2)当指定unitFlags返回多个部分时,相隔的时间由多个部分共同组成(不是独立去表示)。例如:上面的例子时间相差24时15秒,如果指定只返回second部分,将得到86415秒;如果指定返回day和second部分,将得到1天15秒;如果指定返回hour、minute和second,将得到24时0分15秒。

NSCalendar

NSCalendar对世界上现存的常用历法进行了封装,既提供了不同历法的时间信息,又支持日历的计算。

初始化方法

  • + (id)currentCalendar

获取当前客户端的逻辑日历

1
2
NSCalendar *calendar = [NSCalendar currentCalendar];
NSLog(@"%@", calendar.calendarIdentifier);

log信息显示:
gregorian
表示客户端当前是公历

  • - (nullable id)initWithCalendarIdentifier:(NSCalendarIdentifier)ident

根据日历标示符来初始化日历对象

1
2
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierChinese];
NSLog(@"%@", calendar.calendarIdentifier);

log信息显示:
chinese
表示中国农历

系统中定义的有:
NSGregorianCalendar –公历
NSBuddhistCalendar –佛教日历
NSChineseCalendar –中国农历
NSHebrewCalendar –希伯来日历
NSIslamicCalendar –伊斯兰日历
NSIslamicCivilCalendar –伊斯兰教日历
NSJapaneseCalendar –日本日历
NSRepublicOfChinaCalendar –中华民国日历(台湾)
NSPersianCalendar –波斯日历
NSIndianCalendar –印度日历
NSISO8601Calendar – ISO8601

常用方法

  • - (void)setLocale:(NSLocale *)locale

设置本地化信息

1
2
3
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
NSLog(@"%@", calendar.locale.localeIdentifier);

log信息显示:
zh_CN

  • - (void)setTimeZone:(NSTimeZone *)tz

设置时区信息

1
2
3
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Shanghai"]];
NSLog(@"%@", calendar.timeZone);

log信息显示:
Asia/Shanghai (GMT+8) offset 28800

  • - (void)setFirstWeekday:(NSUInteger)weekday

设置每周的第一天从星期几开始,如:1代表星期一开始,2代表星期二开
始,以此类推。默认值是1。

1
2
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[calendar setFirstWeekday:3];
  • - (void)setMinimumDaysInFirstWeek:(NSUInteger)mdw

设置每年及每月第一周必须包含的最少天数, 如:设定第一周最少包括3天,则value传3。

1
2
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setMinimumDaysInFirstWeek:3];

NSDateFormatter

NSDateFormatter的日期格式如下

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
54
55
56
57
58
59
60
G --纪元
一般会显示公元前(BC)和公元(AD)

y --年
假如是2017年,那么yyyy=2017,yy=17

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 --月内的第几周(与日历排列有关)
假如是2017年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的两个最实用的方法是dateFromString和stringFromDate,前者将字符串经过格式化后变成NSDate对象,后者将NSDate对象格式化成字符串。

常用方法

  • setDateFormat

在调setDateFormat设置格式化字符串时,可以使用单
引号来引入其他字符串。

1
2
3
4
5
6
7
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd 'I Love China!' HH:mm:ss"];

NSDate *currentDate = [NSDate date];
NSString *dateStr = [dateFormatter stringFromDate:currentDate];

NSLog(@"%@", dateStr);

log信息显示:
2017-03-26 I Love China! 18:45:14

  • dateFromString

使用NSDateFormatter转换时间字符串时,默认的时区是系统时区,例如在中国都是北京时间(+8),如果直接转换会导致结果相差8小时,所以一般的做法是先指定时区为GMT标准时间再转换。

1
2
3
4
5
6
7
8
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];

NSString *dateStr = @"2017-03-26 18:45:14";
NSDate *date = [dateFormatter dateFromString:dateStr];

NSLog(@"%@",date);

log信息显示:
2017-03-26 18:45:14

CATALOG
  1. 1. NSDateComponents
    1. 1.1. 初始化方法
      1. 1.1.1. 用法一
      2. 1.1.2. 用法二
    2. 1.2. 常用方法
  2. 2. NSCalendar
    1. 2.1. 初始化方法
    2. 2.2. 常用方法
  3. 3. NSDateFormatter
    1. 3.1. 常用方法