【问题标题】:NSDate - one year ago, dilemmaNSDate - 一年前,困境
【发布时间】:2011-01-18 22:35:37
【问题描述】:

我正在尝试做一些对我来说有点困难的事情。但我相信有人有一些见解。

给定一个日期,比如January 17, 2011,我试图找出与一年前的这个日期相对应的日期。所以January 17, 2011 是星期一,而一年前,这一天落在January 18, 2010(也是星期一)。原来January 18, 2010January 17, 2011 早了354 天。我原本以为只是简单地减去非闰年的 365 天和闰年的 366 天,但如果你在这种情况下这样做,你会得到January 17, 2010,这是一个星期日,而不是星期一。

那么,在带有NSDateNSCalendar 的Objective-C 中,我该如何实现这样的功能:

-(NSDate *)logicalOneYearAgo:(NSDate *)from {
}

换句话说,第 n 个月的第 n 个“工作日”(其中“工作日”是星期一、星期二或星期三等)

【问题讨论】:

  • 您必须更好地准确定义您的期望是什么;从 2011 年 1 月 17 日起的一年前是 2010 年 1 月 17 日。您想要(例如)第 n 个月的第 n 个星期一吗?
  • 是的,第n个月的第n个“工作日”。
  • 这个月有五个星期一,而 2010 年 1 月只有四个。在这个日期方案中,2011 年 1 月 31 日之前一年的日期是什么?
  • en.wikipedia.org/wiki/ISO_week_date 日历可能在这里有用。但总的来说,请注意;历法算术在所有情况下都异常难以正确。
  • 我会尝试使用NSCalendar 使用NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekdayOrdinalCalendarUnit | NSWeekdayCalendarUnit 将日期分解为NSDateComponents。但是我还没有尝试过,所以你必须看看你是否可以让它工作。

标签: iphone objective-c ios nsdate nscalendar


【解决方案1】:

你像这样使用 NSDateComponents:

- (NSDate *)logicalOneYearAgo:(NSDate *)from {

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

    NSDateComponents *offsetComponents = [[[NSDateComponents alloc] init] autorelease];
    [offsetComponents setYear:-1];

    return [gregorian dateByAddingComponents:offsetComponents toDate:from options:0];

}

【讨论】:

  • 这导致了我在问题中陈述的问题。如果“from”是 2011 年 1 月 17 日,那么此方法将返回 2010 年 1 月 17 日(但我需要它返回 2010 年 1 月 18 日)。
【解决方案2】:

这在日历计算的Date and Time Programming Guide 部分中进行了介绍,Adding Components to a Date

具体来说,感兴趣的方法是dateByAddingComponents:toDate:options

以 Apple 示例为基础,从当前日期减去一年,您可以执行以下操作:

NSDate *today = [[NSDate alloc] init];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

/*
  Create a date components to represent the number of years to add to the current date.
  In this case, we add -1 to subtract one year.     
*/

NSDateComponents *addComponents = [[NSDateComponents alloc] init];
addComponents.year = - 1;

return [calendar dateByAddingComponents:addComponents toDate:today options:0];

【讨论】:

    【解决方案3】:

    我不能保证这是最有效的方法,但您可以使用 NSCalendarNSDateComponents 来实现。将NSDate 实例传递给[yourCalendar components:yourComponents fromDate:yourDate],从组件中减去一年,然后使用[yourCalendar dateFromComponents:yourComp]

    很抱歉没有提供完整的代码,但我已经有一段时间没有使用这些方法了,我不想给你那些不起作用的代码。

    【讨论】:

    • 这也导致了我在问题中所说的问题。如果“来自”是 2011 年 1 月 17 日,那么这个想法将在 2010 年 1 月 17 日返回(但是我需要它返回 2010 年 1 月 18 日)。
    【解决方案4】:

    减去 1 年。 然后减去 1 天,直到得到所需的一周中的同一天。

    “星期几”每年回退 1 天,除非中间有 2 月 29 日,否则它们回退 2 天。

    这是因为一年是 52 周 + 1 天(闰年 +2)。

    所以,如果你无限期地应用这个逻辑,你最终会年复一年地在 6 月 16 日到 5 月 24 日结束。

    如果您不希望这种情况发生,您必须在某个地方记住参考年份并以此为基础进行算术运算。

    例如,如果“新”星期一是 4 天前(因为 3 年过去了),您可能更愿意选择提前 3 天的星期一,以免年复一年地无限期地减去天数。

    希望对你有帮助。

    【讨论】:

      【解决方案5】:

      答案很简单。结果是反复试验。这是答案。

      如果年份是闰年,则减去 365 天。

      如果年份不是闰年,则减去 364 天。

      【讨论】:

      • 这甚至不能满足您的要求。这个问题及其答案简直是一场灾难。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 2011-04-11
      相关资源
      最近更新 更多