12

当我到 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);
}

这是我的输出:

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

谢谢!

4

2 回答 2

34

欢迎来到日期计算的美妙世界!

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

这个是为了教育你多一点,因为这是一个很难的话题

AnNSDate表示绝对时间点。这一点是不变的。无论人类及其时间测量是否存在,它都会存在。

“天”是一个相对值。它与许多事物相关,例如:

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

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

  • 今年是 2011 年。但是是吗?“2011”相对于公历。如果您不使用公历怎么办?
  • 当前年份是 23。但这仅适用于您使用日本日历,特别是使用日本时代名称的情况。
  • 当前年份是 5771。但前提是您使用的是希伯来日历。并且下一年的营业额(5772)与下一个公历年的营业额不同。
  • 当前年份(可能)是 1432 年。如果您是穆斯林。
  • 如果您是韩国人,则当前年份为 4344。

等等等等。

作为一般规则,大多数日历都是基于太阳的,这意味着围绕太阳的一圈相当于该日历中的一“年”。但这使事情变得非常复杂,因为地球在其围绕太阳的轨道上旋转的次数(“一天”)不是一个整数(整数)。这有点像 365.24 转。进入闰日!但仅限于某些日历!在其他日历中,我们有整个闰月!或闰秒。或闰小时。或跳跃 - 无论你想要什么时间单位。甚至不要让我开始了解时区。

那么,您如何处理呢?

简单的答案:你不会。比你或我聪明得多的人已经编写了代码来为我们处理所有这些。

看:

一个NSCalendar封装了根据该测量系统计算时间(在地球上)的所有规则和规定。 NSDateComponents封装了测量时间的相对性质

因此,您有一个绝对时间点 (an NSDate),并且您想知道它对应于一周中的哪一天。这是你要做的:

  • 获取适当的日历对象。对于您将要做的几乎所有事情,这可能是[NSCalendar currentCalendar].
  • 使用日历,你说“我想要从这个绝对时间点开始的这样那样的'日期组件'”

日历会搅动和燃烧并给你一个NSDateComponents表示你正在寻找的任何信息的信息。

或者假设您有一个绝对时间点,并且您想知道“1 周后的绝对时间点是什么?”。谁知道一周有多长?我不。通常7 天,但不一定是这样。这只是我所熟悉的。但我确信那里有基于非 7 天周的日历。因此,您制作了一个NSDateComponents对象,将其表示为“ 1 周”,然后说“日历:我有这个日期和这个相对数量。添加它们并告诉我新的日期”,它就做到了。

<更新>

但是,将日期组件添加到日期也可能会出现问题。例如,如果您想查找今年每个月的最后一天怎么办?(我们在这里假设公历)所以你从一个NSDate恰好落在 1 月 31 日的日历开始,然后在上面加上“1 个月”。你得到了什么?2月28日!那么你再加上一个月。你得到了什么?3月28日!这已经不是月底了!

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

</更新>

你可以看到这是一个多么困难的话题。如果你还没有,这里有最后一个提示:

这是一个困难的话题

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

于 2011-07-30T22:03:05.267 回答
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);
}
于 2011-07-30T21:10:15.407 回答