Objective c 根据过去的NSDate和重复间隔,计算从现在开始的下一个事件
如何通过重复某个时间间隔,从过去的某个日期计算比现在晚的第一个日期?例如:Objective c 根据过去的NSDate和重复间隔,计算从现在开始的下一个事件,objective-c,cocoa,cocoa-touch,nsdate,date-arithmetic,Objective C,Cocoa,Cocoa Touch,Nsdate,Date Arithmetic,如何通过重复某个时间间隔,从过去的某个日期计算比现在晚的第一个日期?例如: // Date in the past NSDate *pastDate = [NSDate my_dateWithString:@"11/09/2001"]; // Time interval NSTimeInterval repeatInterval = 14 * 24 * 60 * 60; // 2 weeks // Current date NSDate *now = [NSDate date]; // 23
// Date in the past
NSDate *pastDate = [NSDate my_dateWithString:@"11/09/2001"];
// Time interval
NSTimeInterval repeatInterval = 14 * 24 * 60 * 60; // 2 weeks
// Current date
NSDate *now = [NSDate date]; // 23/07/2015
// Start calculating next date ->
NSDate *nextDate = /* interval added to past date */
// Is result later than now?
// No? Calculate again
// Abracadabra
NSLog(@"nexDate = %@",nextDate); // 28/07/2015
我不想使用迭代。我关心的是计算一个案例,比如过去一年的开始日期和一天的重复间隔
这是我的解决方案,但它有迭代
NSDateComponents *twoWeeksDateComponents = [NSDateComponents new];
twoWeeksDateComponents.weekOfMonth = 2;
NSDate *date = self.picker.date;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDate *nextDate = date;
NSComparisonResult result = [nextDate compare:now];
while (result == NSOrderedAscending) {
nextDate = [calendar dateByAddingComponents:kTwoWeeksDateComponents
toDate:nextDate
options:NSCalendarMatchNextTime];
result = [nextDate compare:now];
}
NSLog(@"nexDate = %@",nextDate); // 28/07/2015
您确实可以不用迭代就完成这项工作,而只需使用一点算术。您正在寻找某个因子f严格大于另一个值n的最近倍数。日历计算要复杂一点,但仍然只是算术(当然,所有繁重的工作都由NSCalendar来完成,例如闰年)
从用户处获取您喜欢的重复间隔,并构造一个表示该间隔的
NSDateComponents
:
NSCalendarUnit repeatUnit = NSCalendarUnitWeekOfYear;
NSUInteger repeatInterval = 2;
NSDateComponents * repeatComps = [NSDateComponents new];
[repeatComps setValue:repeatInterval forComponent:repeatUnit];
给定重复单位,查找两个日期之间发生的单位数量,作为另一个日期组件对象:
NSCalendar * cal = [NSCalendar currentCalendar];
NSDateComponents * deltaComps = [cal components:repeatUnit
fromDate:pastDate
toDate:now
options:0];
NSInteger deltaVal = [deltaComps valueForComponent:repeatUnit];
现在是算术位。将增量四舍五入到重复间隔的最近倍数。然后加上舍入值(使用适当的单位)将产生一个等于或早于现在的日期
现在,作为Jawbox,对于NSCalendarUnitMonth
的repeatUnit
,如果使用该值计算日期,然后再添加一个重复间隔(与此答案的原始版本一样),则会得到意外的结果。相反,立即在重复次数上增加一次;然后,日历将正确处理月份增量
NSInteger repeatsJustPastNow = 1 + deltaVal - (deltaVal % repeatInterval);
NSDateComponents * toNowComps = [NSDateComponents new];
[toNowComps setValue:repeatsJustPastNow
forComponent:repeatUnit];
NSDate * nextDate;
nextDate = [cal dateByAddingComponents:toNowComps
toDate:pastDate
options:0];
Jawboxer的。您确实可以不用迭代就完成这项工作,而只需使用一点算术。您正在寻找某个因子f严格大于另一个值n的最近倍数。日历计算要复杂一点,但仍然只是算术(当然,所有繁重的工作都由NSCalendar来完成,例如闰年)
从用户处获取您喜欢的重复间隔,并构造一个表示该间隔的
NSDateComponents
:
NSCalendarUnit repeatUnit = NSCalendarUnitWeekOfYear;
NSUInteger repeatInterval = 2;
NSDateComponents * repeatComps = [NSDateComponents new];
[repeatComps setValue:repeatInterval forComponent:repeatUnit];
给定重复单位,查找两个日期之间发生的单位数量,作为另一个日期组件对象:
NSCalendar * cal = [NSCalendar currentCalendar];
NSDateComponents * deltaComps = [cal components:repeatUnit
fromDate:pastDate
toDate:now
options:0];
NSInteger deltaVal = [deltaComps valueForComponent:repeatUnit];
现在是算术位。将增量四舍五入到重复间隔的最近倍数。然后加上舍入值(使用适当的单位)将产生一个等于或早于现在的日期
现在,作为Jawbox,对于NSCalendarUnitMonth
的repeatUnit
,如果使用该值计算日期,然后再添加一个重复间隔(与此答案的原始版本一样),则会得到意外的结果。相反,立即在重复次数上增加一次;然后,日历将正确处理月份增量
NSInteger repeatsJustPastNow = 1 + deltaVal - (deltaVal % repeatInterval);
NSDateComponents * toNowComps = [NSDateComponents new];
[toNowComps setValue:repeatsJustPastNow
forComponent:repeatUnit];
NSDate * nextDate;
nextDate = [cal dateByAddingComponents:toNowComps
toDate:pastDate
options:0];
Jawboxer's.编辑:正如Josh指出的,这并不能解释闰年。因此,这是一个很好的实现示例,它似乎可以在短期测试中工作,但存在漏洞。它也会在日志中关闭几个小时,因为
dateFromString:
将补偿时区,而日志将记录为GMT
编辑:正如乔希指出的,这并不能解释闰年。因此,这是一个很好的实现示例,它似乎可以在短期测试中工作,但存在漏洞。它也会在日志中关闭几个小时,因为
dateFromString:
将补偿时区,而日志将记录为GMT
我很早就提出了另一个解决方案
NSDate *date = ...;
static NSTimeInterval k2WeeksInterval = 14 * 24 * 60 * 60.0;
NSTimeInterval timeInterval = -date.timeIntervalSinceNow;
double repeats = ceil(timeInterval / k2WeeksInterval);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.weekOfYear = repeats * 2;
NSDate *nextDate = [calendar dateByAddingComponents:components
toDate:date
options:NSCalendarMatchNextTime];
我很早就提出了另一个解决方案
NSDate *date = ...;
static NSTimeInterval k2WeeksInterval = 14 * 24 * 60 * 60.0;
NSTimeInterval timeInterval = -date.timeIntervalSinceNow;
double repeats = ceil(timeInterval / k2WeeksInterval);
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.weekOfYear = repeats * 2;
NSDate *nextDate = [calendar dateByAddingComponents:components
toDate:date
options:NSCalendarMatchNextTime];
最后在看到你的之前发布了我的。。。使用我的可以吗(它似乎总是返回正确的日期,保留时间,并以疯狂的间隔工作,如1周+1天+3小时+4分钟)?或者我应该检查日期组件,而不仅仅是计算时间间隔?你的版本不能很容易地处理月或年的重复单位。例如,尝试使用2015-03-01的开始日期和1年的间隔
NSCalendar
说明了2016年的闰日。NSDateComponents
也可以处理复合间隔。啊,我现在明白了。谢谢。:)这很好,但我想我发现了一个缺陷。假设pastDate
是2015年1月31日,您的repeatUnit
是每月一次,而now
是2015年3月15日-结果是2015年3月28日(而不是3月31日的预期结果)。像我在中所做的那样,将1添加到repeatsToNow
并从中获取nextDate
是否更好?我的修改版本确实给出了预期的3月31日的结果,但也许你这样做还有其他原因?在看到你的之前,我发布了我的。。。使用我的可以吗(它似乎总是返回正确的日期,保留时间,并以疯狂的间隔工作,如1周+1天+3小时+4分钟)?或者我应该检查日期组件,而不仅仅是计算时间间隔?你的版本不能很容易地处理月或年的重复单位。例如,尝试使用2015-03-01的开始日期和1年的间隔NSCalendar
说明了2016年的闰日。NSDateComponents
也可以处理复合间隔。啊,我现在明白了。谢谢。:)这很好,但我想我发现了一个缺陷。假设pastDate
是2015年1月31日,您的repeatUnit
是每月一次,而now
是2015年3月15日-结果是2015年3月28日(而不是3月31日的预期结果)。像我在中所做的那样,将1添加到repeatsToNow
并从中获取nextDate
是否更好?我修改过的版本确实给出了预期的3月31日结果,但可能您这样做还有其他原因吗?这不能很好地处理月份或年份。@Josh Caswell,我想这会很好地工作,因为NSTimeInterval是一个双倍值,计算重复次数可以得到真实结果,但是关于闰年N的计算