美文网首页iOS干货算法或者代码JC专题
iOS学习笔记37-时间和日期计算

iOS学习笔记37-时间和日期计算

作者: 执着丶执念 | 来源:发表于2016-04-19 12:52 被阅读1568次

    一、时间和日期计算

    我们在应用开发中,时常需要和时间打交道,比如获取当前时间,获取两个时间点相隔的时间等等,在iOS开发中与时间相关的类有如下几个:

    1. NSDate:表示一个绝对的时间点
    1. NSTimeZone:时区信息
    2. NSLocale:本地化信息
    3. NSDateComponents:一个封装了具体年月日、时秒分、周、季度等的类
    4. NSCalendar:日历类,它提供了大部分的日期计算接口
    5. NSDateFormatter:用来在日期和字符串之间转换

    二、NSDate时间点

    NSDate存储的是世界标准时(UTC),输出时需要根据时区转换为本地时间

    NSDate常用初始化方法:
    /* 获取当前时间,alloc/init得到的时间也是当前时间 */
    + (instancetype)date;
    /* 以当前时间为基准,获取偏移秒数的时间 */
    + (instancetype)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds;
    /* 以1970年1月1日为基准,获取偏移秒数的时间 */
    + (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds;
    /* 以2001年1月1日为基准,获取偏移秒数的时间 */
    + (instancetype)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds;
    /* 以指定时间点为基准,获取偏移秒数的时间 */
    + (instancetype)dateWithTimeInterval:(NSTimeInterval)seconds 
                               sinceDate:(NSDate *)date;
    /* 获取一个极早的时间点,0001-12-30 00:00:00 +0000 */
    + (instancetype)distantPast;
    /* 获取一个极晚的时间点,4001-01-01 00:00:00 +0000 */
    + (instancetype)distantFuture;
    
    • 除了最后的2个获取极早极晚时间的方法,其他方法都有对应的init前缀方法。
    • 极早和极晚时间常用于定时器的开始和暂停
    • 偏移秒数为正,表示比基准时间晚的时间,偏移秒数为负,表示比基准时间早的时间
    NSDate常用的对象方法:
    /* 以当前NSDate对象为基准,获取偏移指定秒数后得到的新NSDate对象 */
    - (instancetype)dateByAddingTimeInterval:(NSTimeInterval)seconds;
    #pragma mark - 比较2个时间
    /* 比较2个NSDate对象,返回较早的那个NSDate时间点对象 */
    - (NSDate *)earlierDate:(NSDate *)anotherDate;
    /* 比较2个NSDate对象,返回较晚的那个NSDate时间点对象 */
    - (NSDate *)laterDate:(NSDate *)anotherDate;
    /* 比较2个NSDate对象,返回枚举类型(相等、早于、晚于) */
    - (NSComparisonResult)compare:(NSDate *)anotherDate;
    #pragma mark - 获取相隔秒数,从参数时间开始,经过多少秒到达对象执行时间
    /* 返回当前对象时间与1970年1月1日00:00:00的相隔秒数 */
    - (NSTimeInterval)timeIntervalSince1970;
    /* 返回当前对象时间与2001年1月1日00:00:00的相隔秒数 */
    - (NSTimeInterval)timeIntervalSinceReferenceDate;
    /* 返回当前对象时间与当前客户端时间的相隔秒数 */
    - (NSTimeInterval)timeIntervalSinceNow;
    /* 返回当前对象时间与指定时间的相隔秒数 */
    - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;
    
    下面是使用实例:
    /* 获取当前客户端时间 */
    NSDate *date1 = [NSDate date];
    /* 获取比date1晚30秒的时间 */
    NSDate *date2 = [NSDate dateWithTimeInterval:30 sinceDate:date1];
    /* 比较2个时间,获取较早的时间和较晚的时间 */
    NSDate *earlierDate = [date1 earlierDate:date2];
    NSDate *laterDate   = [date1 laterDate:date2];
    NSLog(@"earlierDate:%@,laterDate:%@",earlierDate,laterDate);
    /* 比较2个时间 */
    NSComparisonResult result = [date1 compare:date2];
    switch(result){
        case NSOrderedSame:
            NSLog(@"对象时间等于参数时间");
            break;
        case NSOrderedAscending:
            NSLog(@"对象时间早于参数时间");
            break;
        case NSOrderedDescending:
            NSLog(@"对象时间晚于参数时间");
            break;
    }
    /* 获取相隔时间秒数,将返回结果-30,从date2的时间开始,倒退30秒到达date1的时间 */
    NSTimeInterval seconds = [date1 timeIntervalSinceDate:date2];
    NSLog(@"date1与date2相隔%@秒",seconds);
    

    三、NSTimeZone时区

    NSTimeZone常用初始化方法:
    /* 根据时区名称初始化,例如:America/Chicago(美国芝加哥) */
    + (instancetype)timeZoneWithName:(NSString *)aTimeZoneName;
    /* 根据时区缩写初始化,例如:EST(美国东部标准时间)、HKT(香港标准时间) */
    + (instancetype)timeZoneWithAbbreviation:(NSString *)abbreviation;
    /* 返回系统时区 */
    + (NSTimeZone *)systemTimeZone;
    /* 返回本地时区 */
    + (NSTimeZone *)localTimeZone;
    
    • 时区名称可以通过以下方法获取:
    /* 以数组形式返回所有已知的时区名称 */
    +(NSArray *)knownTimeZoneNames;
    
    • 本地时区和系统时区的区别在于本地时区可以被修改,而系统时区不能修改
    NSTimeZone常用对象方法:
    /* 获取时区名称 */
    - (NSString *)name;
    /* 获取时区缩写 */
    - (NSString *)abbreviation;
    /* 获取对象时区与零时区的间隔秒数 */
    - (NSInteger)secondsFromGMT;
    

    四、NSLocale本地化信息

    NSLocale类返回本地化信息,主要体现在语言区域格式这两个设置项。

    NSLocale常用初始化方法:
    /* 返回系统初始本地化信息 */
    +(instancetype)systemLocale;
    /* 返回当前客户端的本地化信息,即使修改了本地化设定,这个对象也不会改变 */
    +(instancetype)currentLocale;
    /* 返回当前客户端的本地化信息,当每次修改本地化设定,其实例化的对象会随之改变 */
    +(instancetype)autoupdatingCurrentLocale;
    /* 用标示符初始化本地化信息,例如:en_US */
    -(instancetype)initWithLocaleIdentifier:(NSString *)string;
    
    NSLocale常用对象方法:
    /* 根据不同的key返回各种本地化信息 */
    - (id)objectForKey:(id)key;
    /* 显示特定地区代号下相应键的显示名称 */
    - (NSString *)displayNameForKey:(id)key 
                              value:(id)value;
    
    以下是使用实例:
    //获取系统本地化信息
    NSLocale *sysLocale = [NSLocale systemLocale];
    //获取客户端本地化信息,不可响应修改
    NSLocale *curLocale = [NSLocale currentLocale];
    //获取客户端本地化信息,可动态响应修改
    NSLocale *autoCurLocale = [NSLocale autoupdatingCurrentLocale];
    //通过标识创建自定义本地化信息
    NSLocale *userLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
    //获取货币符号
    NSString *strSymbol = [userLocale objectForKey:NSLocaleCurrencySymbol];
    NSLog(@"货币符号:%@",strSymbol);//打印:¥
    //获取本地日历
    NSCalendar *calendar = [userLocale objectForKey:NSLocaleCalendar];
    NSLog(@"本地日历:%@",calendar);
    //得到"en_US"的NSLocaleIdentifier键的显示名称
    NSString *str = [userLocale displayNameForKey:NSLocaleIdentifier value:@"en_US"];
    NSLog(@"标识显示名称:%@",str);//打印:英文(美国)
    

    五、NSDateComponents时间封装

    NSDateComponents封装了具体年月日、时秒分、周、季度等:

    /* 创建一个日期对象 */
    NSDateComponents*compt = [[NSDateComponents alloc] init];
    [compt setEra:1];//纪元
    [compt setYear:2013];//年
    [compt setMonth:3];//月
    [compt setDay:15];//日
    [compt setHour:11];//小时
    [compt setMinute:20];//分钟
    [compt setSecond:55];//秒钟
    [compt setQuarter:2];//几刻钟
    [compt setTimeZone:[NSTimeZone systemTimeZone]];//时区
    [compt setWeek:3];//一年的第几周
    [compt setWeekday:4];//周几
    [compt setWeekOfMonth:3];//一个月的第几周
    [compt setWeekOfYear:3];//一年的第几周
    [compt setCalendar:[NSCalendar currentCalendar]];//日历
    

    NSDateComponents通常不单独使用,它经常与时间点NSDate、日历类NSCalendar一起使用

    六、NSCalendar日历类

    NSCalendar类,表示日历,封装了大量的计算日期方法

    NSCalendar常用创建方法:
    /* 返回客户端的逻辑日历,即使修改了系统日历设定,这个对象也不会改变 */
    +(instancetype)currentCalendar;
    /* 返回客户端的逻辑日历,修改了系统日历设定,这个对象会随之改变 */
    +(instancetype)autoupdatingCurrentCalendar;
    /* 根据提供的日历标示符初始化 */
    -(instancetype)initWithCalendarIdentifier:(NSString *)string;
    
    系统中定义的日历标识符有:
    • NSGregorianCalendar:公历
    • NSBuddhistCalendar:佛教日历
    • NSChineseCalendar:中国农历
    • NSHebrewCalendar:希伯来日历
    • NSIslamicCalendar:伊斯兰历
    • NSIslamicCivilCalendar:伊斯兰教日历
    • NSJapaneseCalendar:日本日历
    • NSRepublicOfChinaCalendar:中华民国日历(台湾)
    • NSPersianCalendar:波斯历
    • NSIndianCalendar:印度日历
    • NSISO8601Calendar:ISO8601日历
    NSCalendar常用的与NSDateComponents相关对象方法:
    /* 
      取得一个NSDate对象的1个或多个部分转为NSDateComponents,
      只有明确指定了unitFlags,NSDateComponents相应的那一部分才有值
     */
    - (NSDateComponents *)components:(NSUInteger)unitFlags 
                            fromDate:(NSDate *)date;
    /* 取得两个NSDate对象的时间间隔,用NSDateComponents来封装 */
    - (NSDateComponents *)components:(NSUInteger)unitFlags 
                            fromDate:(NSDate *)startingDate 
                              toDate:(NSDate*)resultDate 
                             options:(NSUInteger)opts;/* 一般默认传0即可 */
    /* 根据NSDateComponents对象得到一个NSDate对象 */
    - (NSDate *)dateFromComponents:(NSDateComponents *)comps;
    /* 在参数date基础上,增加一个NSDateComponents类型的时间增量 */
    - (NSDate *)dateByAddingComponents:(NSDateComponents *)comps 
                                toDate:(NSDate *)date 
                               options:(NSUInteger)opts;/* 一般默认传0即可 */
    

    unitFlags参数通过下面的日历单位NSCalendarUnit用或运算“|”组合使用

    日历单位NSCalendarUnit,可以用或运算“|”组合使用:
    • NSEraCalendarUnit
      纪元单位。对于NSGregorianCalendar(公历)来说,只有公元前(BC)和公元(AD);而对于其它历法可能有很多,例如日本和历是以每一代君王统治来做计算。
    • NSYearCalendarUnit:年单位。值很大,相当于经历了多少年,未来多少年。
    • NSMonthCalendarUnit:月单位。范围为1-12
    • NSDayCalendarUnit:天单位。范围为1-31
    • NSHourCalendarUnit:小时单位。范围为0-24
    • NSMinuteCalendarUnit:分钟单位。范围为0-60
    • NSSecondCalendarUnit:秒单位。范围为0-60
    • NSWeekCalendarUnit:周单位。范围为1-53
    • NSWeekdayCalendarUnit:星期单位,每周的7天。范围为1-7
    • NSWeekdayOrdinalCalendarUnit:没完全搞清楚
    • NSQuarterCalendarUnit:几刻钟,也就是15分钟。范围为1-4
    • NSWeekOfMonthCalendarUnit:月包含的周数。最多为6个周
    • NSWeekOfYearCalendarUnit:年包含的周数。最多为53个周
    • NSYearForWeekOfYearCalendarUnit:没完全搞清楚
    • NSTimeZoneCalendarUnit:没完全搞清楚
    以下是使用实例:
    //获取客户端逻辑日历
    NSCalendar *calendar = [NSCalendar currentCalendar];
    //获取当前时间
    NSDate *date = [NSDate date];
    //从date中读取年月日,存储在NSDateComponents对象中
    NSDateComponents *compt1 = [calendar components:(NSYearCalendarUnit | 
                                                     NSMonthCalendarUnit | 
                                                     NSDayCalendarUnit) 
                                           fromDate:date];
    
    NSLog(@"年:%d",[compt1 year]);//2016
    NSLog(@"月:%d",[compt1 month]);//4
    NSLog(@"日:%d",[compt1 day]);//19
    /*********************************************************************/
    //创建一个时间相差5小时1分15秒的时间点
    NSDate *date2 = [NSDate dateWithTimeInterval:5*60*60+1*60+15 
                                       sinceDate:date];
    //时间间隔NSDate转NSDateComponents,分钟加秒钟
    NSDateComponents *compt2 = [calendar components:(NSMinuteCalendarUnit | 
                                                     NSSecondCalendarUnit) 
                                           fromDate:date 
                                             toDate:date2 
                                            options:0];
    
    NSLog(@"时间间隔【分种加秒钟】:%d分%d秒",[compt2 minute],[compt2 second]);//301分15秒
    //时间间隔NSDate转NSDateComponents,只有秒钟
    NSDateComponents *compt3 = [calendar components:NSSecondCalendarUnit
                                           fromDate:date 
                                             toDate:date2 
                                            options:0];
    NSLog(@"时间间隔【秒数】:%d秒",[compt3 second]);//18075秒
    /*********************************************************************/
    //创建自定义NSDateComponents对象
    NSDateComponents *compt4 = [[NSDateComponents alloc] init];
    [compt4 setYear:2012];
    [compt4 setMonth:5];
    [compt4 setDay:11];
    //NSDateComponents对象转NSDate对象
    NSDate *newDate = [calendar dateFromComponents:compt4];
    //得到本地时间,避免时区问题
    NSTimeZone *zone = [NSTimeZone systemTimeZone];
    NSInteger interval = [zone secondsFromGMTForDate:newDate];
    NSDate *localeDate = [newDate dateByAddingTimeInterval:interval];
    NSLog(@"NSDateComponents对象转NSDate对象:%@",localeDate);
    /*********************************************************************/
    //创建自定义NSDateComponents对象
    NSDateComponents *compt5 = [[NSDateComponents alloc] init];
    [compt5 setDay:25];
    [compt5 setHour:4];
    [compt5 setMinute:66];
    NSDate *addDate = [calendar dateByAddingComponents:compt5 
                                                toDate:[NSDate date] 
                                               options:0];
    //得到本地时间,避免时区问题
    NSTimeZone *zone2 = [NSTimeZone systemTimeZone];
    NSInteger interval2 = [zone2 secondsFromGMTForDate:addDate];
    NSDate *localeDate2 = [addDate dateByAddingTimeInterval:interval2];
    NSLog(@"NSDate对象追加NSDateComponents对象时间:%@",localeDate2);
    
    NSCalendar类还有一些日历设置和计算的方法:
    /* 设置本地化信息 */
    - (void)setLocale:(NSLocale *)locale;
    /* 设置时区信息 */
    - (void)setTimeZone:(NSTimeZone *)tz;
    /* 设置每周的第一天是从星期几开始,1表示是星期天(默认),2表示星期一,以此类推 */
    - (void)setFirstWeekday:(NSUInteger)weekday;
    /* 设置每年及每月第一周必须包含的最少天数,比如:设定第一周最少包括3天,则value传入3 */
    - (void)setMinimumDaysInFirstWeek:(NSUInteger)value;
    /* 获取一个小的单位在一个大的单位里面的序数 */
    - (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller 
                            inUnit:(NSCalendarUnit)larger 
                           forDate:(NSDate *)date;
    /* 根据参数提供的时间点,得到一个小的单位在一个大的单位里面的取值范围 */
    - (NSRange)rangeOfUnit:(NSCalendarUnit)smaller 
                    inUnit:(NSCalendarUnit)larger 
                   forDate:(NSDate *)date;
    /* 
      根据参数提供的时间点,返回所在日历单位的开始时间。
      如果startDate和interval都计算得出来,则返回YES;否则返回NO
     */
    - (BOOL)rangeOfUnit:(NSCalendarUnit)unit  /* 日历单位 */
              startDate:(NSDate **)datep /* 开始时间,通过参数返回 */
               interval:(NSTimeInterval *)tip /* 日历单位所对应的秒数,通过参数返回 */
                forDate:(NSDate *)date; /* 时间点参数 */
    

    七、NSDateFormatter字符串格式化

    NSDateFormatter专门负责时间NSDate和字符串NSString之间的转换

    下面是格式化符使用规定:
    • 大写G:纪元
      一般会显示公元前(BC)和公元(AD)
    • 小写y:年
      假如是2013年,那么yyyy=2013,yy=13
    • 大写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:月份包含的周(与日历排列有关)
      假如是2013年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 *formatter = [[NSDateFormatter alloc] init];
    //设置时区
    [formatter setTimeZone:[NSTimeZone systemTimeZone]];
    //设置格式化输出格式
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
    //创建时间
    NSDateComponents *compt = [[NSDateComponents alloc] init];
    [compt setYear:2013];
    [compt setMonth:3];
    [compt setDay:13];
    [compt setHour:1];
    [compt setMinute:55];
    [compt setSecond:28];
    //获取日历对象
    NSCalendar *calendar = [NSCalendar currentCalendar];
    //设置时区
    [calendar setTimeZone:[NSTimeZone systemTimeZone]];
    //NSDateComponents对象转NSDate对象
    NSDate *date = [calendar dateFromComponents:compt];
    NSLog(@"date:%@",date);
    //格式化输出字符串,传入要格式化的时间NSDate对象
    NSString *str = [formatter stringFromDate:date];
    NSLog(@"格式化输出:%@",str);
    

    来配图O(∩_∩)O哈哈~:


    详细介绍可以参考这里,讲得很详细:wayne23的博客
    如果有什么问题可以在下方评论区中提出!O(∩_∩)O哈!

    相关文章

      网友评论

      本文标题:iOS学习笔记37-时间和日期计算

      本文链接:https://www.haomeiwen.com/subject/pfnalttx.html