Quantcast
Channel: C++博客-所有随笔
Viewing all articles
Browse latest Browse all 7882

原:关于时间NSDate, NSCalendar, NSDateComponents --2011.11.06

$
0
0
创建:2011.09.15
修改:2011.10.18
修改:2011.11.06


NSDate对象相当于一个时间点,是绝对的。
NSDate考虑事情都是通过转换为NSTimeInterval来进行的.

==========
NSDate objects store dates in absolute time. For example, the date object created in Listing 16 represents 4:00 PM CDT, 5:00 EDT, and so on.

Listing 16  Creating a date from components using a specific time zone

NSCalendar *gregorian=[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];

[gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"CDT"]];

NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init];

[timeZoneComps setHour:16];

//specify whatever day, month, and year is appropriate

NSDate *date=[gregorian dateFromComponents:timeZoneComps];

If you need to create a date that is independent of timezone, you can store the date as an NSDateComponents object—as long as you store some reference to the corresponding calendar.

NSDate使用的是绝对的时间。
NSDateComponents也是绝对的时间。
NSCalendar与TimeZone相关,它会根据TimeZone解释NSDateComponents的意义。比如例子中,[timeZoneComps setHour:16];此时,经过NSCalendar的解释,它就变成了CDT(美国中部时间)的下午4点钟,也就是5:00 EDT(美国东部时间).

==========

In iOS, NSDateComponents objects can contain a calendar, a timezone, and a date object. You can therefore store the calendar along with the components. If you use the date method of the NSDateComponents class to access the date, make sure that the associated timezone is up-to-date.

在iOS中,NSDateComponents并没有很绝对,它绑定了a calendar, a timezone, and a date object。因此,使用的时候,要确保正确的TimeZone. [自:这个不熟,暂时不考虑。]

===========
NSDateComponents可以认为是一个保存了int year, int month, int day, int hour, int minute, int second变量的一个对象。
它没有直接保存为一个date对象。当需要获取NSDate的时候,才动态的计算得到。
并且,每个变量都可以是正数,也可以是负数和0。
但是,不同的变量对于0的解释却不同。对于year,month,day它们不可以为0,因此,一旦设置为0之后,显示的是上一个对应单位的时间。但是对于hour,minute和second却可以为0,只有当设置为-1时,才会显示上一个对应单位的时间。
正常数值如下:
year:1~Max
month:1~12
day:1~365/366
hour:0~23
minute:0~59
second:0~59

测试代码如下:
假设当前时间为:2010-10-10 10:10:10

===========
常用代码:
计算Date偏移:
    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
    
    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *comps = [cal components:unitFlags fromDate:date];
    
    [comps setMonth:([comps month] - 1)];
     [comps setDay:0];
    [comps setHour:0];
    
    NSDate *resDate  = [cal dateFromComponents:comps];
   [cal release];

通过NSString得到NSDate:
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm zzzz"];
    
    NSDate *dateFormString = [formatter dateFromString:@"2011-08-31 05:00 -0400"];


通过NSDate得到NSString:
    NSDate *date = [NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setTimeZone:[NSTimeZone timeZoneWithName:@"America/New_York"]];
    [formatter setDateFormat:@"MM/dd/yyyy hh:mma"];
    NSString *dateStr = [NSString stringWithFormat:@"%@", [formatter stringFromDate:date]];


格林尼治标准时间的时区可以认为是:GMT。即-0000或+0000.
[cal setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];

中国时区横跨东五区、东六区、东七区、东八区、东九区等五个地理时区。中国大陆所有区域使用的标准时间均为东八区(UTC+8)(+0800)时间,比协调世界时或格林尼治标准时间快8小时。

美国本土横跨西五区至西十区,共六个时区,每个时区对应一个标准时间。从东向西分别为东部时间(EST)(西五区时间-0500)、中部时间(CST) (西六区时间-0600)、山地时间(MST)(西七区时间)、太平洋时间(西部时间)(PST)(西八区时间)、阿拉斯加时间(AKST)(西九区时 间)和夏威夷时间(HST)(西十区时间),按照“东早西晚”的规律,各递减一小时。

美国从每年3月的第二个星期日至11月的第一个星期日采用夏令时,夏令时比正常时间早一小时。当处于夏令时时,相当于向东移动了一个时区,此时东部时间(EST)(西五区时间)可以认为从-0500变成了-0400,依次类推。

时区的计算:
要计算的区时=已知区时-(已知区时的时区-要计算区时的时区),(注:东时区为正,西时区为负)。 

北京(东八区)时间为5月10日12:00
东京(东九区)时间为5月10日13:00  =12:00-(8-9)=13:00
伦敦(中时区)时间为5月10日4:00    =12:00-(8-0)=4:00
纽约(西五区)时间为5月9日23:00    =12:00-[8-(-5)]=-1:00+24:00-1天=23:00

    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |
    NSDayCalendarUnit | NSHourCalendarUnit |
    NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateFormatter *f = [[NSDateFormatter alloc] init];
    [f setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
    NSDate *d = [f dateFromString:@"2010-10-10 10:10:10"];
    NSDateComponents *comps = [cal components:unitFlags fromDate:d];
    NSDate *theStartDate  = [cal dateFromComponents:comps];
    NSLog(@"%@ Src", theStartDate);
    [comps setYear:1];
    theStartDate  = [cal dateFromComponents:comps];
    NSLog(@"%@ setYear:1", theStartDate);    
    comps = [cal components:unitFlags fromDate:d];
    [comps setYear:0];
    theStartDate  = [cal dateFromComponents:comps];
    NSLog(@"%@ setYear:0" , theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setYear:-1];
    theStartDate  = [cal dateFromComponents:comps];
    NSLog(@"%@ setYear:-1", theStartDate);
    
    comps = [cal components:unitFlags fromDate:d];
    [comps setMonth:1];
    theStartDate  = [cal dateFromComponents:comps];
    NSLog(@"%@ setMonth:1", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setMonth:0];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setMonth:0", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setMonth:-1];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setMonth:-1", theStartDate);

    comps = [cal components:unitFlags fromDate:d];
    [comps setDay:1];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setDay:1", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setDay:0];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setDay:0", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setDay:-1];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setDay:-1", theStartDate);
    
    comps = [cal components:unitFlags fromDate:d];
    [comps setHour:0];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setHour:0", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setHour:24];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setHour:24", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setHour:-1];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setHour:-1", theStartDate);
    
    comps = [cal components:unitFlags fromDate:d];
    [comps setMinute:0];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setMinute:0", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setMinute:60];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setMinute:60", theStartDate);
    comps = [cal components:unitFlags fromDate:d];
    [comps setMinute:-1];
    theStartDate  = [cal dateFromComponents:comps];    
    NSLog(@"%@ setMinute:-1", theStartDate);

结果如下:
2010-10-10 14:10:10 +0000 Src
0001-10-12 14:10:10 +0000 setYear:1
0001-10-12 14:10:10 +0000 setYear:0
0002-10-12 14:10:10 +0000 setYear:-1
2010-01-10 14:10:10 +0000 setMonth:1
2009-12-10 14:10:10 +0000 setMonth:0 // 设置0变成上一年的最后一个月了。
2009-11-10 14:10:10 +0000 setMonth:-1 // 设置-1变成上一年的最后二个月了。
2010-10-01 14:10:10 +0000 setDay:1
2010-09-30 14:10:10 +0000 setDay:0 // 设置0变成上一月的最后一天了。
2010-09-29 14:10:10 +0000 setDay:-1 // 设置-1变成上一月的最后天了。
// 以上的时间范围都是从0开始,以下的时间范围都是从1开始。因此0和-1的概念都发生了变化(例如:-1的意义都变成了从“二”变为“一”)。
2010-10-10 00:10:10 +0000 setHour:0
2010-10-11 00:10:10 +0000 setHour:24  // 超过24变成下一天了。
2010-10-09 23:10:10 +0000 setHour:-1 // 设置-1变成上一天的最后小时了。
2010-10-10 14:00:10 +0000 setMinute:0
2010-10-10 15:00:10 +0000 setMinute:60 // 超过60变成下一小时了。
2010-10-10 13:59:10 +0000 setMinute:-1


=====
week是一年中的第几周,weekOfYear也是一年中的几周。在Gregorian日历中应该没有区别。

weekday是该日期是这一周中第几天。范围是从1-7。星期日是1。(其实,weekday要由日历的类型来解释的。weekday返回的是该日历类型中,比weekday大一个单位的单位中,该日期是排名第几。当然,对于Gregorian来说,比

weekday大一的单位就是月。但是,对于其他日历来说也许不是这样的

 

weekOfMonth是指该日期是本月的第几周。一周从星期日开始。

weekdayOrdinal是指该日期是本月的第几个星期几。有点混乱啊。结合weekOfMonth举个例子:
如果本月是从周二开始的,即1号是周二,2号是周三,6号是周日,7号是周一,8号是第二个周二。
那么如果日期设定为1,2,3,4,5号的话,则weekOfMonth和weekdayOrdinal都是1
那么如果日期设定为6,7号的话,则weekOfMonth是2,但是weekdayOrdinal却是1,因为6号虽然是第二周,但是却是本月第一个周日,同样7号虽然也是第二周,但是却是本月第一个周一。

那么如果日期设定为8,9,10......号的话,则weekOfMonth和weekdayOrdinal都是2

+++++

佳为好友 2012-12-29 10:56 发表评论

Viewing all articles
Browse latest Browse all 7882

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>