假设我有一个约会,我想做两件事:
- 将小时重置为指定的小时。
- 将一天增加一定数量。
通过阅读文档,您似乎需要使用两个不同的步骤:
// 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 的天数?这是未定义的行为,还是它遵循了一些记录在案的规则集?
最佳答案
我没有真正的证据或文档引用,但我发现了一些迹象表明这种在日期计算中的“回绕”确实有效。
NSCalendar
是免费桥接到它的核心基础对应物,CFCalendarRef
.来自源代码 CFCalendar.c 人们可以看到所有的日历计算都是使用 ICU Calendar Classes .
Calendar class 有一个方法
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);
最后,来自 calendar.cpp 中的构造函数可以看到默认的“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 日,被“宽大”对待。
关于objective-c - 使用 dateFromComponents 时,将 NSDateComponents 中的日期设置为大于 31 的日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22134686/