Objective c 计算数组中特定月份的日期数
我有一个Objective c 计算数组中特定月份的日期数,objective-c,cocoa,nsdate,date-arithmetic,Objective C,Cocoa,Nsdate,Date Arithmetic,我有一个NSDate对象数组,我想知道从现在到五个月前,每个月有多少个条目 这是否可以使用NSPredicate?您必须测试数组中的日期6次 第一:匹配7月1日当天或之后至8月1日之前的所有日期。 第二:匹配6月1日当天或之后至7月1日之前的所有日期。 第三:匹配5月1日当天或之后至6月1日之前的所有日期。 等等 在循环中创建两个日期。第一个日期是月初的午夜。第二个日期正好是1个月之后。然后从数组中筛选出第一个日期当天或之后第二个日期之前的所有日期。在循环的下一个迭代中,您使startDate比
NSDate
对象数组,我想知道从现在到五个月前,每个月有多少个条目
这是否可以使用
NSPredicate
?您必须测试数组中的日期6次
第一:匹配7月1日当天或之后至8月1日之前的所有日期。第二:匹配6月1日当天或之后至7月1日之前的所有日期。
第三:匹配5月1日当天或之后至6月1日之前的所有日期。
等等 在循环中创建两个日期。第一个日期是月初的午夜。第二个日期正好是1个月之后。然后从数组中筛选出第一个日期当天或之后第二个日期之前的所有日期。在循环的下一个迭代中,您使startDate比上一个startDate早一个月 大量的日期计算,但在NSDateComponents的帮助下,这并不是什么大问题 由于我不确定如何在数组中使用NSPredicate和NSDates,我使用了另一种方法,但基本上是这样工作的:
NSDateComponents *oneMonthOffset = [[NSDateComponents alloc] init];
oneMonthOffset.month = 1;
NSDateComponents *thisMonth = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit fromDate:[NSDate date]];
thisMonth.day = 1;
NSDate *startOfCurrentMonth = [calendar dateFromComponents:thisMonth];
for (NSInteger offset = 0; offset > -5; offset--) {
NSDateComponents *startDateOffset = [[NSDateComponents alloc] init];
startDateOffset.month = offset;
NSDate *startDate = [calendar dateByAddingComponents:startDateOffset toDate:startOfCurrentMonth options:0];
NSDate *endDate = [calendar dateByAddingComponents:oneMonthOffset toDate:startDate options:0];
NSIndexSet *matchingIndexes = [array indexesOfObjectsPassingTest:^BOOL(NSDate *date, NSUInteger idx, BOOL *stop) {
if ([date compare:startDate] != NSOrderedAscending && [date compare:endDate] == NSOrderedAscending) {
// date is not before startDate (i.e. is on startDate or later than startDate) and date is before endDate
return YES;
}
return NO;
}];
NSLog(@"%d dates after %@ and before %@", [matchingIndexes count], [startDate descriptionWithLocale:[NSLocale currentLocale]], [endDate descriptionWithLocale:[NSLocale currentLocale]]);
}
如果您的日期数组非常大,您可能希望首先对其进行排序,并且只扫描相关范围。此代码当前测试阵列中的所有NSDATE 您必须测试数组中的日期6次 第一:匹配7月1日当天或之后至8月1日之前的所有日期。
第二:匹配6月1日当天或之后至7月1日之前的所有日期。
第三:匹配5月1日当天或之后至6月1日之前的所有日期。
等等 在循环中创建两个日期。第一个日期是月初的午夜。第二个日期正好是1个月之后。然后从数组中筛选出第一个日期当天或之后第二个日期之前的所有日期。在循环的下一个迭代中,您使startDate比上一个startDate早一个月 大量的日期计算,但在NSDateComponents的帮助下,这并不是什么大问题 由于我不确定如何在数组中使用NSPredicate和NSDates,我使用了另一种方法,但基本上是这样工作的:
NSDateComponents *oneMonthOffset = [[NSDateComponents alloc] init];
oneMonthOffset.month = 1;
NSDateComponents *thisMonth = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit fromDate:[NSDate date]];
thisMonth.day = 1;
NSDate *startOfCurrentMonth = [calendar dateFromComponents:thisMonth];
for (NSInteger offset = 0; offset > -5; offset--) {
NSDateComponents *startDateOffset = [[NSDateComponents alloc] init];
startDateOffset.month = offset;
NSDate *startDate = [calendar dateByAddingComponents:startDateOffset toDate:startOfCurrentMonth options:0];
NSDate *endDate = [calendar dateByAddingComponents:oneMonthOffset toDate:startDate options:0];
NSIndexSet *matchingIndexes = [array indexesOfObjectsPassingTest:^BOOL(NSDate *date, NSUInteger idx, BOOL *stop) {
if ([date compare:startDate] != NSOrderedAscending && [date compare:endDate] == NSOrderedAscending) {
// date is not before startDate (i.e. is on startDate or later than startDate) and date is before endDate
return YES;
}
return NO;
}];
NSLog(@"%d dates after %@ and before %@", [matchingIndexes count], [startDate descriptionWithLocale:[NSLocale currentLocale]], [endDate descriptionWithLocale:[NSLocale currentLocale]]);
}
如果您的日期数组非常大,您可能希望首先对其进行排序,并且只扫描相关范围。此代码当前测试阵列中的所有NSDATE 与Matthias的方法有些不同,尽管我也不认为使用
NSPredicate
可以实现这一点,因为这里需要日期算法
这将从每个日期开始创建日期组件,并使用NSCountedSet
对这些组件进行计数。(您可能可以对计数集使用谓词。)然后创建另一个描述您感兴趣的月份和年份的NSDateComponents
对象,并使用countForObject:
NSArray * dates = @[/* Your dates here */];
NSCalendar * cal = [NSCalendar currentCalendar];
/* Convert the dates into date components objects for month and year. */
NSMutableArray * months = [NSMutableArray array];
for( NSDate * date in dates ){
NSDateComponents * month = [cal components:(NSMonthCalendarUnit|NSYearCalendarUnit)
fromDate:date];
[months addObject:month];
}
/* Count the unique components. */
NSCountedSet * monthsCounts = [NSCountedSet setWithArray:months];
/* Use a predicate here on the set? */
/* A components object for month arithmetic. */
NSDateComponents * monthDelta = [NSDateComponents new];
/* Get month names for the current locale. */
NSDateFormatter * formatter = [NSDateFormatter new];
NSArray * monthNames = [formatter monthSymbols];
for( NSInteger i = 0; i > -NUM_MONTHS; i-- ){
/* Couting backwards from the current month, get a date components
* object for each month and year.
*/
[monthDelta setMonth:i];
NSDateComponents * currMonth;
currMonth = [cal components:(NSMonthCalendarUnit|NSYearCalendarUnit)
fromDate:[cal dateByAddingComponents:monthDelta
toDate:[NSDate date]
options:0]];
/* Get the count from the counted set and display. */
NSUInteger count = [monthsCounts countForObject:currMonth];
NSLog(@"%lu dates in %@", count,
[monthNames objectAtIndex:[currMonth month] - 1]);
}
与Matthias的方法有些不同,尽管我也看不到使用
NSPredicate
实现这一点的好方法,因为这里需要日期算法
这将从每个日期开始创建日期组件,并使用NSCountedSet
对这些组件进行计数。(您可能可以对计数集使用谓词。)然后创建另一个描述您感兴趣的月份和年份的NSDateComponents
对象,并使用countForObject:
NSArray * dates = @[/* Your dates here */];
NSCalendar * cal = [NSCalendar currentCalendar];
/* Convert the dates into date components objects for month and year. */
NSMutableArray * months = [NSMutableArray array];
for( NSDate * date in dates ){
NSDateComponents * month = [cal components:(NSMonthCalendarUnit|NSYearCalendarUnit)
fromDate:date];
[months addObject:month];
}
/* Count the unique components. */
NSCountedSet * monthsCounts = [NSCountedSet setWithArray:months];
/* Use a predicate here on the set? */
/* A components object for month arithmetic. */
NSDateComponents * monthDelta = [NSDateComponents new];
/* Get month names for the current locale. */
NSDateFormatter * formatter = [NSDateFormatter new];
NSArray * monthNames = [formatter monthSymbols];
for( NSInteger i = 0; i > -NUM_MONTHS; i-- ){
/* Couting backwards from the current month, get a date components
* object for each month and year.
*/
[monthDelta setMonth:i];
NSDateComponents * currMonth;
currMonth = [cal components:(NSMonthCalendarUnit|NSYearCalendarUnit)
fromDate:[cal dateByAddingComponents:monthDelta
toDate:[NSDate date]
options:0]];
/* Get the count from the counted set and display. */
NSUInteger count = [monthsCounts countForObject:currMonth];
NSLog(@"%lu dates in %@", count,
[monthNames objectAtIndex:[currMonth month] - 1]);
}