NSDateComponents - 返回错误日期的日方法

Mat*_* W. 11 iphone nsdatecomponent

当我到了2011年11月6日时,我似乎无法弄清楚为什么这一天不会发生变化.我所做的一切都在迭代.任何帮助,将不胜感激.这是我的代码:

NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comp = [[NSDateComponents alloc] init];

[comp setDay:2];
[comp setMonth:11];
[comp setYear:2011];

NSDate* date = [calendar dateFromComponents:comp];

for (int i = 0; i < 7; i++) {
    NSDate* d = [date dateByAddingTimeInterval:((3600 * 24) * i)];
    NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];

    int day = [dComponents day];
    NSLog(@"\nDate: %@\nDay: %i", [d description], day);
}
Run Code Online (Sandbox Code Playgroud)

这是我的输出:

Date: 2011-11-02 06:00:00 +0000
Day: 2

Date: 2011-11-03 06:00:00 +0000
Day: 3

Date: 2011-11-04 06:00:00 +0000
Day: 4

Date: 2011-11-05 06:00:00 +0000
Day: 5

Date: 2011-11-06 06:00:00 +0000
Day: 6

Date: 2011-11-07 06:00:00 +0000
Day: 6

Date: 2011-11-08 06:00:00 +0000
Day: 7
Run Code Online (Sandbox Code Playgroud)

谢谢!

Dav*_*ong 34

欢迎来到日期计算的精彩世界!

@Vladimir是对的.11月6日恰好有大约90,000秒,因为那时(在阳历中的美国),夏令时生效.接受他的回答; 这是正确的.

这个是为了教育你一点,因为这是一个难题.

An NSDate表示绝对时间点.这一点是不可改变的.无论人类及其时间测量是否存在,它都将存在.

"日"是相对值.这与许多事情有关,例如:

  1. 地球.火星日与地球日不同
  2. 进行计算的人的日历.并非所有日历都以相同的方式测量时间.

因此,在没有更多上下文的情况下,不可能获取相对值并将其添加到绝对值.你不知道的相对价值是相对的.您假设每个人都使用与您相同的参考点,并且该假设是错误的.例如:

  • 今年是2011年.但是呢?"2011"与格里高利历有关.如果您没有使用公历,该怎么办?
  • 当前年份为23.但这只是在您使用日历并特别使用日本时代名称的情况下.
  • 今年是5771.但这只是在你使用希伯来日历时.明年的营业额(5772)与下一个格里高利年的营业额不同.
  • 当前年份(可能)是1432年.如果你是穆斯林.
  • 如果你是韩国人,那么今年是4344.

等等等等.

作为一般规则,大多数日历都是基于太阳的,这意味着围绕太阳的一个轨道相当于该日历中的一个"年".但是这使事情变得非常复杂,因为地球围绕太阳旋转的旋转次数("天")不是一个整体(整数).这就像365.24轮换.输入闰日!但只在某些日历中!在其他日历中,我们有整个闰月!或者闰秒.或者闰小时.或者你想要的任何时间单位跳跃.甚至不让我开始时区.

那么,你怎么处理这个?

答案很简单:你没有.人们比你聪明得多,或者我已经编写了代码来处理所有这些问题.

看吧:

一个NSCalendar根据测量的该系统封装所有的规则和规章,用于计算时间(在地球上). NSDateComponents包含了测量时间的相对性质.

所以你有一个绝对的时间点(a NSDate),你想知道它对应的星期几.这是你做的:

  • 获取适当的日历对象.对于你将要做的几乎所有事情,这可能是[NSCalendar currentCalendar].
  • 使用日历,你会说"我希望从这个绝对时间点出现这样的'日期组件'"

日历将流失并燃烧,并返回一个NSDateComponents表示您正在寻找的任何信息.

或者,假设你有一个绝对的时间点,你想知道"一周之后的绝对时间点是多少?".谁知道一周有多长?我不.这是通常 7天,但它并没有要.这就是我熟悉的.但我确信那里有基于非7天周的日历.所以你制作一个NSDateComponents对象,抨击它意味着"1周",然后说"日历:我有这个日期和这个相对数量.添加它们并告诉我新的日期",它就是这样做的.

<更新>

但是,将日期组件添加到日期也可能会有问题.例如,如果你想找到今年每个月的最后一天怎么办?(我们将在这里假设公历)所以你从NSDate1月31日开始的时候开始,然后加上"1个月".你得到了什么?2月28日!那么你加一个月就可以了.你得到了什么?3月28日!那不是本月底了!

解决这个问题的方法是始终从原始日期计算新日期.因此,不是每个连续日期添加1个月,而是在原始日期添加"n"个月.这将正常工作.

</更新>

你可以看到这是一个困难的话题.万一你没有,这是最后一个提示:

这是一个困难的话题

你越早学会正确地做事,你和你的代码就越快乐.:)


Vla*_*mir 20

11月6日是由于节约时间而改变时间的一天,因此这一天实际上持续25小时并且可能来自那个不正确的结果(通常由于日历不规则和日期可能取决于日期,因此添加时间间隔是不可靠的许多参数:当前日历,时区,区域设置等).

迭代几天的更正确的方法(每个wwdc11视频"执行日历计算"(iTunes链接))是在每次迭代的开始日期添加适当数量的日期组件:

...
NSDateComponents *addComponents = [[NSDateComponents alloc] init];
for (int i = 0; i < 7; i++) {
    [addComponents setDay: i];
    NSDate* d = [calendar dateByAddingComponents:addComponents toDate:date options:0];        
     NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];

     int day = [dComponents day];
     NSLog(@"\nDate: %@\nDay: %i", [d description], day);
}
Run Code Online (Sandbox Code Playgroud)

  • +1绝对正确.这也被称为不是每天都有86,400秒的错误 (8认同)