• iOS 时间处理(转)


    NSDate

    1. NSDate对象用来表示一个具体的时间点。
    2. NSDate是一个类簇,我们所使用的NSDate对象,都是NSDate的私有子类的实体。
    3. NSDate存储的是GMT时间,使用的时候会根据 当前应用 指定的 时区 进行时间上的增减,以供计算或显示。

    可以快速地获取的时间点有:

    now    (当前时间点)
    相对于1 January 2001, GMT的时间点
    相对于1970的时间点
    distantFuture   (不可达到的未来的某个时间点)
    distantPast     (不可达到的过去的某个时间点
    

    根据http://www.gnustep.org/实现的NSDate的版本:

    <!-- lang: cpp -->
    @interface NSDate : NSObject  <NSCoding, NSCopying>
    {
        NSTimeInterval _secondsSinceRef;
    }
    
    ……
    
    - (id) initWithTimeInterval:(NSTimeInterval) secsToBeAdded
                  sinceDate:(NSDate *) anotherDate;       相对于已知的某个时间点
    - (id) initWithTimeIntervalSinceNow:(NSTimeInterval) secsToBeAdded;        相对于当前时间
    - (id) initWithTimeIntervalSince1970:(NSTimeInterval)seconds;        相对于1970年1月1日0时0分0秒
    - (id) initWithTimeIntervalSinceReferenceDate:(NSTimeInterval) secs;       相对于2001年1月1日0时0分0秒
    
    ……
    
    @end
    

    可以看出,NSDate类确实只是一个相对的时间点,NSTimeInterval的单位是秒(s),_secondsSinceRef则说明NSDate对象是相对于ReferenceDate(2001年1月1日0时0分0秒)的一个时间点。

    同时,根据Cocoa框架的设计原则,每个类都有一个“指定初始化方法”(指定初始化方法是参数最全,且其他初始化方法都会调用的初始化方法)。http://www.gnustep.org/实现的版本以方法:

    <!-- lang: cpp -->
    - (id) initWithTimeIntervalSinceReferenceDate:(NSTimeInterval) secs;
    

    作为指定初始化方法,也就是说所有的时间点都转化为了相对referenceDate的时间点(时间点都是相对的,因为时间本身就是相对的)。

    NSDate中最常用的方法一般是:

    <!-- lang: cpp -->
    NSDate *now = [NSDate date];    // [[NSDate alloc] init]
    NSDate *dateFromNow = [NSDate dateWithTimeIntervalSinceNow:60];
    NSDate *dateFromAnotherDate = [[NSDate alloc] initWithTimeInterval:60 sinceDate:dateFromNow];
    
    NSTimeInterval timeInterval1 = [now timeIntervalSinceDate:dateFromNow];
    NSTimeInterval timeInterval2 = [now timeIntervalSinceNow];
    
    
    
    //-------------------------------------------------------------
    NSDate *distantPast = [NSDate distantPast];          //  可以表示的最早的时间
    NSDate *distantFuture = [NSDate distantFuture];      //  可以表示的最远的未来时间
    
    NSString *stringDate = @"12/31/9999";
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
    [dateFormatter setDateFormat:@"MM/dd/yyyy"];
    NSDate *dateCheck = [dateFormatter dateFromString:stringDate];
    NSLog(@"Date = %@", dateCheck);
    
    Output:
    Date = 1999-12-30 16:00:00 +0000
    
    *iOS中用NSDate表示的时间只能在distantPast和distantFuture之间!
    //-------------------------------------------------------------
    

    NSDateFormatter

    NSDateFormatter是NSFormatter的子类,另,NSFormatter的用途是“将数据在字符串与特定类型的对象之间转换”,目前NSFormatter只有两个子类NSNumberFormatter和NSDateFormatter。

    尽管NSDateFormatter提供了许多已定义好的时间格式,但是开发中开发人员更加喜欢自定义时间格式。

    1. 将时间字符串转换到NSDate对象,一般都是使用"年月日 时分秒”,数据库中的date类型基本上也是这样的时间类型。 格式一般为:yyyy-MM-dd HH:mm:ss。

      注意:yyyy是小写的;大写的YYYY的意思有些不同——“将这一年中第一周的周日当作今年的第一天”,因此有时结果和yyyy相同,有时就会不同。

    2. 将NSDate对象转换成特定格式的字符串。

      转换后的字符串会根据设备的“区域格式”,显示特定语言的结果。假如程序需要保证不同语言环境下显示一致,请注意这方面的问题,使用其他代替方法!

      一言足以明志:

      <!-- lang: cpp -->
      NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
      [dateFormatter setDateFormat:@"'公元前/后:'G  '年份:'u'='yyyy'='yy '季度:'q'='qqq'='qqqq '月份:'M'='MMM'='MMMM '今天是今年第几周:'w '今天是本月第几周:'W  '今天是今天第几天:'D '今天是本月第几天:'d '星期:'c'='ccc'='cccc '上午/下午:'a '小时:'h'='H '分钟:'m '秒:'s '毫秒:'SSS  '这一天已过多少毫秒:'A  '时区名称:'zzzz'='vvvv '时区编号:'Z "];
      NSLog(@"%@", [dateFormatter stringFromDate:[NSDate date]]);
      

      OutPut:

      1. 区域格式:美国

        公元前/后:AD  年份:2013=2013=13 季度:3=Q3=3rd quarter 月份:8=Aug=August 今天是今年第几周:32 今天是本月第几周:2  今天是今天第几天:219 今天是本月第几天:7 星期:4=Wed=Wednesday 上午/下午:AM 小时:1=1 分钟:24 秒:32 毫秒:463  这一天已过多少毫秒:5072463  时区名称:China Standard Time=China Standard Time 时区编号:+0800
        
      2. 区域格式:中国

        公元前/后:公元  年份:2013=2013=13 季度:3=三季度=第三季度 月份:8=8月=8月 今天是今年第几周:32 今天是本月第几周:2  今天是今天第几天:219 今天是本月第几天:7 星期:4=周三=星期三 上午/下午:上午 小时:1=1 分钟:44 秒:30 毫秒:360  这一天已过多少毫秒:6270360  时区名称:中国标准时间=中国标准时间 时区编号:+0800
        
    3. 过多使用NSDateFormatter将影响程序的性能,且程序中NSDateFormatter对象的时间格式基本一致,所以使用NSDateFormatter的时候尽量使用单例模式。

    !!!!奉上NSDateFormatter的时间格式: 更详细的官方说明

    a:  AM/PM
    A:  0~86399999 (Millisecond of Day)
    
    c/cc:   1~7 (Day of Week)
    ccc:    Sun/Mon/Tue/Wed/Thu/Fri/Sat
    cccc: Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday
    
    d:  1~31 (0 padded Day of Month)
    D:  1~366 (0 padded Day of Year)
    
    e:  1~7 (0 padded Day of Week)
        E~EEE:  Sun/Mon/Tue/Wed/Thu/Fri/Sat
    EEEE: Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday
    
    F:  1~5 (0 padded Week of Month, first day of week = Monday)
    
    g:  Julian Day Number (number of days since 4713 BC January 1)
        G~GGG:  BC/AD (Era Designator Abbreviated)
    GGGG:   Before Christ/Anno Domini
    
    h:  1~12 (0 padded Hour (12hr))
    H:  0~23 (0 padded Hour (24hr))
    
    k:  1~24 (0 padded Hour (24hr)
    K:  0~11 (0 padded Hour (12hr))
    
    L/LL:   1~12 (0 padded Month)
    LLL:    Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec
    LLLL: January/February/March/April/May/June/July/August/September/October/November/December
    
    m:  0~59 (0 padded Minute)
    M/MM:   1~12 (0 padded Month)
    MMM:    Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec
    MMMM: January/February/March/April/May/June/July/August/September/October/November/December
    
    q/qq:   1~4 (0 padded Quarter)
    qqq:    Q1/Q2/Q3/Q4
    qqqq:   1st quarter/2nd quarter/3rd quarter/4th quarter
    Q/QQ:   1~4 (0 padded Quarter)
    QQQ:    Q1/Q2/Q3/Q4
    QQQQ:   1st quarter/2nd quarter/3rd quarter/4th quarter
    
    s:  0~59 (0 padded Second)
    S:  (rounded Sub-Second)
    
    u:  (0 padded Year)
    
    v~vvv:  (General GMT Timezone Abbreviation)
    vvvv:   (General GMT Timezone Name)
    
    w:  1~53 (0 padded Week of Year, 1st day of week = Sunday, NB: 1st week of year starts from the last Sunday of last year)
    W:  1~5 (0 padded Week of Month, 1st day of week = Sunday)
    
    y/yyyy: (Full Year)
    yy/yyy: (2 Digits Year)
    Y/YYYY: (Full Year, starting from the Sunday of the 1st week of year)
    YY/YYY: (2 Digits Year, starting from the Sunday of the 1st week of year)
    
    z~zzz:  (Specific GMT Timezone Abbreviation)
    zzzz:   (Specific GMT Timezone Name)
    Z:  +0000 (RFC 822 Timezone)
    

    NSTimeZone

    **时区是一个地理名字,是为了克服各个地区或国家之间在使用时间上的混乱。

    基本概念:

    1. GMT 0:00 格林威治标准时间; UTC +00:00 校准的全球时间; CCD +08:00 中国标准时间 [来自百度百科]
    2. 夏时制,英文"DaylightSavingTime”。夏季时将时区内的时间提前(一般为1小时),以节省资源,提高效率。使用夏时制期间,当前时区相对于GMT的时间偏移量会发生变化。在某些应用中可能需要考虑。
    3. 任 何时区都以GMT为基准,即,任何NSTimeZone对象所代表的时区都是相对于GMT的,这里的相对性是NSTimeZone中最重要的属性,我们称 之为当前时区相对于GMT的偏移量。一旦知道了一个偏移量,便可以确定一个时区。在iOS中,偏移量是以"秒"为单位的。
    4. NSTimeZone是一个类簇,我们所使用的任何NSTimeZone对象都是NSTimeZone的私有子类。
    5. iOS中的时间类NSDate中存储的时间,都是相对于GMT的,我们使用NSDate时,会根据App的时区设置返回与时区对应的数据。
    6. iOS系统中的/usr/share/zoneinfo/目录中保存了所有的可根据 地理位置名称 或 时区别名 得到的时区信息。时区别名都是与具体的地理位置一一对应的。(已越狱的童鞋请看)
    7. iOS中的时区表示方法:GMT+0800 GMT-0800。(+:东区 -:西区 08:小时数 00:分钟数)。 GMT+0830就是指比GMT早8小时外加30分钟的时区。

    由方法理解NSTimeZone

    1. 第一批

      // 这个方法的名字很委婉,known一词说明这是“他”已知的时区的名字。世界各地对自己所在的时区可能都有一定的命名,但是不一定被“他”收录。例如,中国大陆,只有重庆和上海被收录了(难道这是中国只使用一个时区的错误?!)。使用这个方法获得的时区名字,都是在iOS系统中/usr/share/zoneinfo/目录中保存时区数据。随着iOS版本的更新,这里面的数据会发生变动。当然,要是你的设备越狱了,你可以手动往该目录下添加时区文件。       
      // 时区文件里面包括了一下内容:
      //      当前时区相对于GMT的偏移量(s)
      //      当前时区的名字缩写
      //      当前时区是否使“夏时制”时区
      // 因为时区文件中包含了"偏移量",所以通过“时区的名称”可以指定一个“时区”。
      // 时区名称举例:
      //      Africa/Abidjan
      //      America/New_York
      //      Asia/Shanghai
      //      Asia/Hong_Kong
      // 越狱的童鞋可以看出时区的名称和/usr/share/zoneinfo中的目录结构基本一一对应。
      + (NSArray *)knownTimeZoneNames;
      
      
      // 获取所有的时区名称缩写
      // 名称缩写与名称是一一对应的关系,例如:HKT = "Asia/Hong_Kong";
      // 默认情况下,调用该方法回去/usr/share/zoneinfo目录下找时区名称缩写,但是当使用方法"+ (void)setAbbreviationDictionary:(NSDictionary *)dict;"后,将会只返回刚才设置的时区名称缩写。请看下文的代码实例!
      // 名称缩写举例:
      //      EST = "America/New_York";
      //      GMT = GMT;
      //      GST = "Asia/Dubai";
      //      HKT = "Asia/Hong_Kong";
      + (NSDictionary *)abbreviationDictionary;
      
    2. 第二批

      //  由时区的名称获得对应的NSTimeZone对象
      //  通过时区名称可以获得时区文件,通过时区文件就可以获得“偏移量”,“名称缩写”,“是否使用夏时制”等信息。
      + (id)timeZoneWithName:(NSString *)tzName;
      
      //  由时区名称缩写获得对应的NSTimeZone对象
      //  这里的时区名称缩写有两种情况:
      //  第一种是上面说的HKT这样的缩写,与时区名称一一对应,通过这样的缩写获得的NSTimeZone对象,与使用时区名称获得得NSTimeZone对象一样。(大概读取得是同一个时区文件)
      //  第二种是"GMT+0800"这样格式得缩写,其实这就是偏移量。通过偏移量在iOS中是不能读到与之对应得时区文件的,因此就无法知道“时区名称”,“名称缩写”,“是否使用夏时制”这样的信息了。默认情况下,"时区名称"和"名称缩写"都会赋值为"GMT+0800","是否使用夏时制"则不会设置(默认不使用)。
      + (id)timeZoneWithAbbreviation:(NSString *)abbreviation;
      
      //  由偏移量获得对应的NSTimeZone对象
      //  只说一点:通过偏移量获得的NSTimeZone对象的“市区名称”,“名称缩写”都会赋值为"GMT+0800","是否使用夏时制"则不会设置(默认不使用)。
      //  注意!!!!该方法不做参数的范围检查!!!
      + (id)timeZoneForSecondsFromGMT:(NSInteger)seconds;       // 不做安全性检查
      

    NSTimeZone的属性变量(猜想):

    // 当前时区与GMT的偏移量,以秒为单位  可通过方法"- (NSInteger)secondsFromGMT;"获取,中国标准时区的偏移量为(8*60*60)。
    // 这是NSTimeZone类中最基本的属性,类似于NSDate中的_secondsSinceRef属性。
    // 其他的属性都是为了丰富NSTimeZone,以实现offset与具体的地理位置以及与时区相关的其他信息的绑定。
    //  对应方法:- (NSInteger)secondsFromGMT;
    int offset;
    
    // 时区的名称,
    // 对应方法:- (NSString *)name;
    NSString *_name;
    
    // 时区名称缩写
    // 对应方法:- (NSString *)abbreviation;
    NSString *abbrev;
    
    // 时区文件数据
    // 对应方法:- (NSData *)data;
    NSData *_data;
    
    // 时区是否使用夏时制
    // 对应方法:- (BOOL)isDaylightSavingTime;
    BOOL is_dst;
    

    代码实例:

    时区对时间的影响

       <!-- lang: cpp -->
    // 修改默认时区会影响时间的输出显示
     [NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0900"]]; // 只能够修改该程序的defaultTimeZone,不能修改系统的,更不能修改其他程序的。
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    
    NSDate *now = [NSDate date];
    NSLog(@"now:%@", [dateFormatter stringFromDate:now]);
    
    // 也可直接修改NSDateFormatter的timeZone变量
    dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];
    NSLog(@"now:%@", [dateFormatter stringFromDate:now]);
    

    添加中国标准时间名称缩写

        <!-- lang: cpp -->
    // 设置并获取时区的缩写
    NSMutableDictionary *abbs = [[NSMutableDictionary alloc] init];
    [abbs setValuesForKeysWithDictionary:[NSTimeZone abbreviationDictionary]];
    [abbs setValue:@"Asia/Shanghai" forKey:@"CCD"];
    [NSTimeZone setAbbreviationDictionary:abbs];
    NSLog(@"abbs:%@", [NSTimeZone abbreviationDictionary]);
    

    夏天了!注意夏时制!

        <!-- lang: cpp -->
    // 因为“夏时制”而产生的方法
    - (NSInteger)secondsFromGMTForDate:(NSDate *)aDate;
    - (NSString *)abbreviationForDate:(NSDate *)aDate;
    - (BOOL)isDaylightSavingTimeForDate:(NSDate *)aDate;
    - (NSTimeInterval)daylightSavingTimeOffsetForDate:(NSDate *)aDate NS_AVAILABLE(10_5, 2_0);
    - (NSDate *)nextDaylightSavingTimeTransitionAfterDate:(NSDate *)aDate NS_AVAILABLE(10_5, 2_0);
    

    NSLocale

    若你只开发中国区的应用,需要保证用户修改当前语言环境时应用的显示不发生变化。而像NSDateFormatter这样的类,会根据设备的设置,自动返回不同语言的数据。为了保证返回数据的语言一致,我们需要设置NSLocale。

    <!-- lang: cpp -->
    
    <!-- lang: cpp -->
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh"];
    NSDateFormatter *secondDateFormatter = [[NSDateFormatter alloc] init];
    [secondDateFormatter setDateFormat:@"cccc"];
    secondDateFormatter.locale = locale;
    NSDate *date = [NSDate date];
    NSLog(@"%@", [secondDateFormatter stringFromDate:date]);
    

    当然,像上面的需求很罕见。

    作为大家都不常用的一个类,NSLocale类是将与国家和语言相关的信息进行简单的组合,包括货币,文学方面的信息。 
    货币:货币的国际名称(人民币的国际货币名称是CNY);货币符号(人民币的国际货币符号是¥) 
    文学:标点符号,文字的书写顺序(左右顺序),引用的起止符号等等 
    若做金融一类的应用可能会用到NSLocale这个类。

    这个类稍微了解即可。

    NSCalendar + NSDateComponents

    1. 历法能使人类确定每一日再无限的时间中的确切位置并记录历史。
    2. 日历,历法,一般历法都是遵循固定的规则的,具有周期性。日历都是已知的或可预测的。
    3. 任何一种具体的历法,首先必须明确规定起始点,即开始计算的年代,这叫“纪元”;以及规定一年的开端,这叫“岁首”。此外,还要规定每年所含的日数,如何划分月份,每月有多少天等等。
    4. NSCalendar对世界上现存的常用的历法进行了封装,既提供了不同历法的时间信息,又支持日历的计算。
    5. NSDateFomatter表示的时间默认以公历(即阳历)为参考,可以通过设置calendar属性变量获得特定历法下的时间表示。
    6. NSDate是独立与任何历法的,它只是时间相对于某个时间点的时间差;NSDate是进行日历计算的基础。
    7. NSDateComponents 将时间表示成适合人类阅读和使用的方式,通过NSDateComponents可以快速而简单地获取某个时间点对应的“年”,“月”,“日”,“时”, “分”,“秒”,“周”等信息。当然一旦涉及了年月日时分秒就要和某个历法绑定,因此NSDateComponents必须和NSCalendar一起使 用,默认为公历。
    8. NSDateComponents除了像上面说的表示一个时间点外,还可以表示时间段,例如:两周,三个月,20年,7天,10分钟,50秒等等。时间段用于日历的计算,例如:获取当前历法下,三个月前的某个时间点。
    9. 可以说,要获取某个时间点在某个历法下的表示,需要NSDateComponents;要计算当前时间点在某个历法下对应的一个时间段前或后的时间点,需要NSDateComponents。
    10. NSDateComponents返回的day, week, weekday, month, year这一类数据都是从1开始的。因为日历是给人看的,不是给计算机看的,从0开始就是个错误。

    NSDateComponents实例化的方式

    第一种:
        <!-- lang: cpp -->
    //  先定义一个遵循某个历法的日历对象
    NSCalendar *greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    //  通过已定义的日历对象,获取某个时间点的NSDateComponents表示,并设置需要表示哪些信息(NSYearCalendarUnit, NSMonthCalendarUnit, NSDayCalendarUnit等)
    NSDateComponents *dateComponents = [greCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit | NSWeekOfMonthCalendarUnit | NSWeekOfYearCalendarUnit fromDate:[NSDate date]];
    NSLog(@"year(年份): %i", dateComponents.year);
    NSLog(@"quarter(季度):%i", dateComponents.quarter);
    NSLog(@"month(月份):%i", dateComponents.month);
    NSLog(@"day(日期):%i", dateComponents.day);
    NSLog(@"hour(小时):%i", dateComponents.hour);
    NSLog(@"minute(分钟):%i", dateComponents.minute);
    NSLog(@"second(秒):%i", dateComponents.second);
    
    //  Sunday:1, Monday:2, Tuesday:3, Wednesday:4, Friday:5, Saturday:6
    NSLog(@"weekday(星期):%i", dateComponents.weekday);
    
    //  苹果官方不推荐使用week
    NSLog(@"week(该年第几周):%i", dateComponents.week);
    NSLog(@"weekOfYear(该年第几周):%i", dateComponents.weekOfYear);
    NSLog(@"weekOfMonth(该月第几周):%i", dateComponents.weekOfMonth);
    

    若获取dateComponents对象时,设置components的时候未添加 NSYearCalendarUnit,dateComponents.year将返回错误的数值,其他的也一样,所以使用 NSDateComponents表示时间时,要确保需要使用的数据都在componets中添加了。

    第二种:
        <!-- lang: cpp -->
    //  先定义一个遵循某个历法的日历对象
    NSCalendar *greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    //  定义一个NSDateComponents对象,设置一个时间点
    NSDateComponents *dateComponentsForDate = [[NSDateComponents alloc] init];
    [dateComponentsForDate setDay:6];
    [dateComponentsForDate setMonth:5];
    [dateComponentsForDate setYear:2004];
    
    //  根据设置的dateComponentsForDate获取历法中与之对应的时间点
    //  这里的时分秒会使用NSDateComponents中规定的默认数值,一般为0或1。
    NSDate *dateFromDateComponentsForDate = [greCalendar dateFromComponents:dc];
    
    
    
    
    //  定义一个NSDateComponents对象,设置一个时间段
    NSDateComponents *dateComponentsAsTimeQantum = [[NSDateComponents alloc] init];
    [dateComponentsForDate setDay:6];
    
    //  在当前历法下,获取6天后的时间点
    NSDate *dateFromDateComponentsAsTimeQantum = [greCalendar dateByAddingComponents:dateComponentsAsTimeQantum toDate:[NSDate date] options:0];
    
    第三种:
        <!-- lang: cpp -->
    //  先定义一个遵循某个历法的日历对象
    NSCalendar *greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    //  根据两个时间点,定义NSDateComponents对象,从而获取这两个时间点的时差
    NSDateComponents *dateComponents = [greCalendar components:NSYearCalendarUnit fromDate:[NSDate dateWithTimeIntervalSince1970:0] toDate:[NSDate date] options:0];
    NSLog(@"number of years:%i", dateComponents.year);
    

    NSCalendar中比较重要的方法和概念

    firstWeekday

    firstWeekday是大家比较容易浑淆的东西。

    大家在使用dateComponents.weekday获取某天对应的星期时,会发现,星期日对应的值为1,星期一对应的值为2,星期二对应的值为3, 依次递推,星期六对应的值为7,这与我们平时理解的方式不一样。然后,我们就开始找是不是可以设置这种对应关系。终于,我们在NSCalendar中发现 了firstWeekday这个变量,从字面意思上看貌似就是我们寻找的那个东西。可是,设置过firstWeekday后,我们又发现完全没有作用,真 是郁闷啊!其实,大家不必郁闷,因为郁闷也没用,iOS中规定的就是周日为1,周一为2,周二为3,周三为4,周四为5,周五为6,周六为7,无法通过某 个设置改变这个事实的,只能在使用的时候注意一下这个规则了。那firstWeekday是干什么用的呢?大家设置一下firstWeekday,再获取 一下dateComponents.weekOfYear或dateComponents.weekOfMonth,看看返回的数据是否发生了变化。 firstWeekday的作用确实是修改当前历法中周的起始位置,但是不能修改周日对应的数值,只能修改一年或一个月中周的数量,以及周的次序。

    -(NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
    答疑解惑:
    1. Unit:单元

    2. NSRange:

      typedef struct _NSRange {

          NSUInteger location;
      NSUInteger length;
      

      } NSRange;

    我们大致可以理解为:某个时间点所在的“小单元”,在“大单元”中的数量(返回值range的location属性变量的值一般是错误的)。例如:

                <!-- lang: cpp -->
        //  当前时间对应的月份中有几天
        [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length;
        //  当前时间对应的月份中有几周(前面说到的firstWeekday会影响到这个结果)
        [[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length;
    
    -(NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;

    我们大致可以理解为:某个时间点所在的“小单元”,在“大单元”中的位置(从1开始)。例如:

               <!-- lang: cpp -->
        //  当前时间对应的周是当前年中的第几周
        [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekOfYearCalendarUnit inUnit:NSYearCalendarUnit forDate:self];
        [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]];
    
        //  当前时间对应的周是当前月中的第几周
        [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekOfMonthCalendarUnit inUnit:NSYearCalendarUnit forDate:self];
        [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]];
    

    在这里:NSWeekOfYearCalendarUnit, NSWeekOfMonthCalendarUnit与NSWeekCalendarUnit的使用结果相同,为了避免浑淆,建议在此处使用 NSWeekCalendar,而定义NSDateComponents时使用NSWeekOfYearCalendarUnit和 NSWeekOfMonthCalendarUnit。

    -(BOOL)rangeOfUnit:(NSCalendarUnit)unit startDate:(NSDate *)datep interval:(NSTimeInterval )tip forDate:(NSDate *)date;

    我们大致可以理解为:“某个时间点”所在的“单元”的起始时间,以及起始时间距离“某个时间点”的时差(单位秒)。例如:

        <!-- lang: cpp -->
        NSDate *startDateOfYear;
        NSDate *startDateOfMonth;
        NSDate *startDateOfWeek;
        NSDate *startDateOfDay;
        NSTimeInterval TIOfYear;
        NSTimeInterval TIOfMonth;
        NSTimeInterval TIOfWeek;
        NSTimeInterval TIOfDay;
        [[NSCalendar currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startDateOfYear interval:&TIOfYear forDate:[NSDate date]];
        [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startDateOfMonth interval:&TIOfMonth forDate:[NSDate date]];
        [[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startDateOfWeek interval:&TIOfWeek forDate:[NSDate date]];
        [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startDateOfDay interval:&TIOfDay forDate:[NSDate date]];
        NSLog(@"firstDateOfYear:%@, FirstDateOfMonth:%@, FirstDateOfWeek:%@, FirstDateOfDay:%@", startDateOfYear, startDateOfMonth, startDateOfWeek, startDateOfDay);
        NSLog(@"TIOfYear:%f, TIOfMonth:%f, TIOfWeek:%f, TIOfDay:%f", TIOfYear, TIOfMonth, TIOfWeek, TIOfDay);
    

    关于NSCalendar和NSDateComponents的介绍暂时说到这里。 
    到目前为止,已经将iOS开发中关于时间的基本知识介绍完毕,欠缺之处请各位积极批评。

  • 相关阅读:
    Matlab编辑器背景修改
    Booksim的运行
    illustrator画梯形
    latex去掉页眉
    latex字体颜色
    latex字体
    Methods to reduce the number of pipeline stages
    Basic Router Architecture
    Linux /sbin/service脚本一个基本无影响的bug
    HTML5实战之桌面通知
  • 原文地址:https://www.cnblogs.com/6duxz/p/4613840.html
Copyright © 2020-2023  润新知