远离懵壁,看懂这篇NSDate

4,041 阅读5分钟

UTC世界标准时间,由原子钟计算,我们现在使用的时间标准,UTC表示0时区。

GMT格林尼治时间,由英国格林尼治天文台统一度量,通过它来区分时区。



时间和时间戳

获得时间通过初始化NSDate来获取我们需要的时间对象,转换成string表示

获得时间戳通过某一个时间对象到UNIX(1970年1月1日00:00:00 UTC)时间的差值,转换成string表示

当前时间和UTC时间

UTC表示0时区时间是统一的时间标准,当前时间表示带有GMT修饰的时区时间


NSDate

初始化

NSDate *date = [NSDate new];//init方法用来初始化当前日期和UTC时间
NSDate *date = [NSDate date];//UTC时间,0时区
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];//比标准UTC增加或减少秒
NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];//从UTC1970-01-01 00:00:00开始增加或减少秒数
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:1];//UTC从2001-01-01 00:00:00l开始增加或减少秒数
NSDate *date = [NSDate dateWithTimeInterval:interval sinceDate:date];//从指定日期开始增加或减少秒数

时间转时间戳

- (NSString *)getTimestamp:(NSString *)time {
    NSDateFormatter *format = [NSDateFormatter new];
    format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSDate *date = [format dateFromString:time];
    NSInteger timeInterval = [date timeIntervalSince1970];
    NSString *timestamp = [NSString stringWithFormat:@"%ld",(long)timeInterval];
    return timestamp;
}

时间戳转时间

- (NSString *)getTime:(NSString *)timestamp {
    NSDateFormatter *format = [NSDateFormatter new];
    format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSTimeInterval timeInterval = [timestamp integerValue];
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    NSString *time = [format stringFromDate:date];
    return time;
}

NSDate时间转NSString时间

第一种:字符串不包含GMT时区缩写,timeZone定义为GMT0时区
- (void)timeString {
	NSDate *date = [NSDate date];
    NSDateFormatter *format = [NSDateFormatter new];//自定义时间标准
    format.dateFormat = @"yyy-MM-dd HH:mm:ss";
    format.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
    NSString *datestr = [format stringFromDate:date];
}

第二种:字符串包含GMT时区缩写,dateFormat定义@"yyy-MM-dd HH:mm:ss Z",字符串后面GMT缩写改为+0000
- (void)timeString {
    NSDate *date = [NSDate date];
    NSTimeZone *zone = [NSTimeZone systemTimeZone];
    NSDateFormatter *format = [NSDateFormatter new];//自定义时间标准
    format.dateFormat = @"yyy-MM-dd HH:mm:ss Z";
    NSUInteger interval = [zone secondsFromGMTForDate:date];//当前时区和UTC时区的秒数差
    NSDate *currentdate = [date dateByAddingTimeInterval:interval];//获得当前时区的date对象
    NSString *datestr = [format stringFromDate:date];
}

不推荐第二种,且不说通过yyyy-MM-dd HH:mm:ss Z获得的时间对象每次都有GMT,需要通过修改字符串内的GMT为+0000的麻烦程度,代码量增加,而且转换成功后的NSDate为0时区的当前时间(这句理解很重要),在我们通过它的值来计算其它时区的时候会出现错误。

更推荐第一种,取NSDate时尽量不要取GMT,代码量少,减少了不必要的NSDate计算,直接使用NSDate转NSString更准确

NSString时间转NSDate

字符串时间转NSDate,等于把时间转换成0时区UTC
- (void)timedate {
    NSDate *date = [NSDate date];
    NSDateFormatter *format = [NSDateFormatter new];//自定义时间标准
    format.dateFormat = @"yyy-MM-dd HH:mm:ss";
    NSDate *daStr = [format dateFromString:@"2019-07-06 21:21:05"];
}

时间比较和计算

比较是否相等

BOOL bl = [date isEqualToDate:date];

比较早晚

NSDate *earlier = [date earlierDate:daStr];//比较两个时间,获得之前的时间
NSDate *later = [date laterDate:daStr];//比较两个时间,获得之后的时间

NSDateFormatter

dateFormat 常用

@"yyy-MM-dd HH:mm:ss Z"//GMT格式
@"yyyy-MM-dd"
@"HH:mm:ss"
@"yyyy-MM-dd HH:mm:ss"//hh表示12小时制
@"yyyy-MM-dd HH:mm:ss:sss"//精确到毫秒13位

timeZone NSTimeZone

  • name :时区名称

  • secondsFromGMT:当前时区和UTC的秒数差

  • abbreviation :GMT的缩写

//用时区名称、缩写来定义时区
[NSTimeZone timeZoneWithName:zone.abbreviation];

//用时间差来定义时区
[NSTimeZone timeZoneForSecondsFromGMT:zone.secondsFromGMT];

timeStyle

时/分 (12小时格式)
NSDateFormatterShortStyle;

时/分/秒 (12小时格式)
NSDateFormatterMediumStyle;

时/分/秒 (12小时 GMT格式)
NSDateFormatterLongStyle;

NSDateComponents

NSDateComponents是通过NSCalendar日历对象,完成对日期时间的控制

初始化

NSDate *date = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];//日历对象
NSDateComponents *comp = [calendar components:
                              NSCalendarUnitYear |
                              NSCalendarUnitMonth |
                              NSCalendarUnitDay |
                              NSCalendarUnitHour |
                              NSCalendarUnitMinute |
                              NSCalendarUnitSecond |
                              NSCalendarUnitTimeZone |
                              NSCalendarUnitWeekday  fromDate:date];
//	comp.year		年
//	comp.month		月
//	comp.day		日
//	comp.hour		时
//	comp.minute		分
//	comp.second		秒
//	comp.timeZone	时区信息(name/abbreviation/secondsFromGMT)

获得星期

NSCalendarUnitWeekday 当前星期几
NSCalendarUnitWeekOfYear 单位为年条件下,属于第几周
NSCalendarUnitWeekOfMonth 单位为月条件下,属于第几周

获得精确日历单位

- (void)getDayUnit {
    NSDate *date = [NSDate date];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];//日历类型
    NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitYear forDate:date];//较小日历单位在较大日历单位内的绝对时间值范围
}

日历类型 NSCalendarIdentifierChinese 表示中国农历,NSCalendarIdentifierGregorian 表示公历

获得计算后日历单位给定的日期组件添加到给定的日期计算出的绝对日期

- (void)getNewComp {
    NSDate * date = [NSDate date];
    NSDateComponents * comp = [[NSDateComponents alloc] init];
    comp.year = -1;//属性为无符号,-表示之前日历单位,+表示未来日历单位
    comp.day = 1;
    comp.hour = 2;
    NSCalendar * calendar = [NSCalendar currentCalendar];
    //comp:组件,date:日期,NSCalendarMatchStrictly:向前或向后(日期计算方式)
    NSDate * newData = [calendar dateByAddingComponents:comp toDate:date options:NSCalendarMatchStrictly];
    NSDateFormatter * formatter = [NSDateFormatter new];
    formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
    NSString * time = [formatter stringFromDate:newData];
}

NSDateComponents日期组件转NSDate时间

NSDateComponents * comp = [[NSDateComponents alloc] init];
comp.year = 2019;//组件如果不设置,就默认为初始值
comp.month = 7;
comp.day = 9;
comp.hour = 13;
comp.minute = 14;
NSCalendar * calendar = [NSCalendar currentCalendar];
NSDate * date = [calendar dateFromComponents:comp];
NSDateFormatter * formatter = [NSDateFormatter new];
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
NSString * str = [formatter stringFromDate:date];


最后

技术总结:

1.我们经常遇到时间戳转换,无论是时间还是时间戳,一定要知道这两个到底是什么。

2.在转换中我们经常看到UTC和实际时间的时区差,这里结合时区去理解整个计算方式。

3.format可以把它看作一个可控的百宝箱,为你提供各种便捷的操作服务;calendar就是一个管家帮助NSDateComponents完成对日期的控制;而Components里面则有很多组件用来随意使用对日期功能的丰富扩展。

4.另外初始化NSDate时间很重要,以上大多数都是[NSDate date]初始化方式,当你看完整篇文章结合自己的理解,也可以通过传入某一时间对以上所写的功能进行封装灵活运用。