Objective c 使用dateFromComponents时,是否将NSDateComponents中的日期设置为大于31?

Objective c 使用dateFromComponents时,是否将NSDateComponents中的日期设置为大于31?,objective-c,nsdate,nsdatecomponents,Objective C,Nsdate,Nsdatecomponents,假设我有个约会,我想做两件事: 将小时重置为指定的小时 每天增加一定数量 通过阅读文档,您似乎需要使用两个不同的步骤: // Step 1: Get today at 9 AM. NSDateComponents *todayComponents = [[NSCalendar currentCalendar] components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitD

假设我有个约会,我想做两件事:

  • 将小时重置为指定的小时
  • 每天增加一定数量
  • 通过阅读文档,您似乎需要使用两个不同的步骤:

    // Step 1: Get today at 9 AM.
    NSDateComponents *todayComponents = [[NSCalendar currentCalendar] components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ) fromDate:[NSDate date]];
    [todayComponents setHour:9];
    NSDate *todayAt9AM = [[NSCalendar currentCalendar] dateFromComponents:todayComponents];
    
    // Step 2: Add one day to that date.
    NSDateComponents *oneDay = [NSDateComponents new];
    [oneDay setDay:1];
    NSDateComponents *tomorrowAt9AM = [[NSCalendar currentCalendar] dateByAddingComponents:oneDay toDate:todayAt9AM options:0];
    
    然而,似乎有一条捷径只涉及一个步骤:

    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear ) fromDate:[NSDate date]];
    components.hour = 9;
    components.day += 1;
    NSDate *tomorrowAt9AM = [[NSCalendar currentCalendar] dateFromComponents:components];
    
    即使日期是2014年1月31日,这似乎也能起作用,准确地说是在2014年2月1日上午9点左右

    这似乎很奇怪,因为您正在发送dateFromComponents以下值:

    • 年份:2014年
    • 月份:1
    • 日期:32
    • 小时:9
    • 分钟:34(例如)
    • 秒数:12(例如)
    请注意,32在公历中是如何超出范围的

    依赖此快捷方式是否危险(例如,如果它只是碰巧起作用)?或者有没有dateFromComponents的文档说明可以这样使用它

    另外,它如何知道何时需要包装,何时需要显式重写其中一个值


    假设我将月份设置为3,它会将月份保留为3,还是先处理我指定的月份(3),然后处理可能将月份增加到4的天数?这是一种未定义的行为,还是它遵循了一套记录在案的规则?

    我没有真正的证据或文件参考,但我发现一些指标表明,这种“环绕”在日期计算中实际起作用

    • 是免费的桥接到它的核心基础对应物,

    • 从源代码 可以看出,所有历法计算都是使用

    • 有一个方法
      setLenient

      /**
       * Specifies whether or not date/time interpretation is to be lenient. With lenient
       * interpretation, a date such as "February 942, 1996" will be treated as being
       * equivalent to the 941st day after February 1, 1996. With strict interpretation,
       * such dates will cause an error when computing time from the time field values
       * representing the dates.
       *
       * @param lenient  True specifies date/time interpretation to be lenient.
       *
       * @see            DateFormat#setLenient
       * @stable ICU 2.0
       */
      void setLenient(UBool lenient);
      
    • 最后,从中的构造函数可以看出默认的“宽松”值是
      TRUE

      Calendar::Calendar(UErrorCode& success)
      :   UObject(),
          fIsTimeSet(FALSE),
          fAreFieldsSet(FALSE),
          fAreAllFieldsSet(FALSE),
          fAreFieldsVirtuallySet(FALSE),
          fNextStamp((int32_t)kMinimumUserStamp),
          fTime(0),
          fLenient(TRUE),
          fZone(0)
      {
          clear();
          fZone = TimeZone::createDefault();
          setWeekCountData(Locale::getDefault(), NULL, success);
      }
      
    把所有这些放在一起,我们就得到了这个设置

    components.month = 1;
    components.day = 32;
    

    在1月1日后的第31天,即2月1日,“宽大”处理。

    该宽大是否也适用于其他组件(月、小时、分钟、秒)?例如,如果我将年设置为2014年,月设置为13,日设置为1(2014-13-01),它会将日期设置为2015-01-01吗?@senseve:我的实验表明,它也适用于其他组件,这就是我理解“宽松”属性的方式。不幸的是,我没有“证据”。真有趣!它看起来像是从最大到最小(年、月、日、时、分、秒)处理组件吗?这将解释它如何知道何时要换行,而不是显式设置值。@senseve:是的,看起来是这样。-我们可以通过分析ICU日历方法精确地回答这个问题,因为源代码是可用的:-)