Это две части:
Я собираюсь вытащить две другие должности, чтобы выручить меня.
В выходные дни мне нужно знать день недели на определенную дату.Для этого пригодится этот пост: Как проверить, какой это день недели (т.е. вторник, пятница?) И сравнить два NSDates?
Для праздников у @vikingosegundo естьдовольно большое предложение на этот пост: Список всех американских праздников как NSDates
Сначала давайте разберемся с выходными;
Я включил предложение в посте, который я цитировал выше, в эту милую маленькую вспомогательную функцию, которая сообщает нам, является ли дата днем недели:
BOOL isWeekday(NSDate * date)
{
int day = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:date] weekday];
const int kSunday = 1;
const int kSaturday = 7;
BOOL isWeekdayResult = day != kSunday && day != kSaturday;
return isWeekdayResult;
}
Нам понадобится способчтобы увеличить дату на указанное количество дней:
NSDate * addDaysToDate(NSDate * date, int days)
{
NSDateComponents * components = [[NSDateComponents alloc] init];
[components setDay:days];
NSDate * result = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:date options:0];
[components release];
return result;
}
Нам нужен способ пропустить выходные дни:
NSDate * ensureDateIsWeekday(NSDate * date)
{
while (!isWeekday(date))
{
// Add one day to the date:
date = addDaysToDate(date, 1);
}
return date;
}
И нам нужен способ добавить произвольное количество днейна дату:
NSDate * addBusinessDaysToDate(NSDate * start, int daysToAdvance)
{
NSDate * end = start;
for (int i = 0; i < daysToAdvance; i++)
{
// If the current date is a weekend, advance:
end = ensureDateIsWeekday(end);
// And move the date forward by one day:
end = addDaysToDate(end, 1);
}
// Finally, make sure we didn't end on a weekend:
end = ensureDateIsWeekday(end);
return end;
}
- Примечание;Я пропустил очевидную оптимизацию - вы можете легко добавить более одного дня за раз к текущей дате - но смысл моего поста в том, чтобы показать вам, как это сделать самостоятельно - и не обязательно придумывать лучшее из возможныхрешение.
Теперь давайте свяжем это и посмотрим, что у нас получилось:
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDate * start = [NSDate date];
int daysToAdvance = 10;
NSDate * end = addBusinessDaysToDate(start, daysToAdvance);
NSLog(@"Result: %@", [end descriptionWithCalendarFormat:@"%Y-%m-%d"
timeZone:nil
locale:nil]);
[pool drain];
return 0;
}
Итак, у нас есть выходные дни, теперь нам нужно потянутьв праздничные дни.
Добавление какого-либо RSS-канала или данных из другого источника определенно выходит за рамки моего поста ... так что давайте просто предположим, что у вас есть какие-то даты, которые, как вы знаете, являются выходными или, согласноВ вашем рабочем календаре выходной.
Теперь я собираюсь сделать это с NSArray ... но, опять же, это оставляет много места для улучшений - как минимум, его нужно отсортировать.А еще лучше, какой-то хэш-набор для быстрого поиска дат.Но этого примера должно быть достаточно, чтобы объяснить концепцию.(Здесь мы создаем массив, который указывает, что через два и три дня будут выходные)
NSMutableArray * holidays = [[NSMutableArray alloc] init];
[holidays addObject:addDaysToDate(start, 2)];
[holidays addObject:addDaysToDate(start, 3)];
И реализация этого будет очень похожа на выходные.Мы позаботимся о том, чтобы день не был выходным.Если это так, мы перейдем к следующему дню.Итак, набор методов, которые помогут с этим:
BOOL isHoliday(NSDate * date, NSArray * holidays)
{
BOOL isHolidayResult = NO;
const unsigned kUnits = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents * components = [[NSCalendar currentCalendar] components:kUnits fromDate:date];
for (int i = 0; i < [holidays count]; i++)
{
NSDate * holiday = [holidays objectAtIndex:i];
NSDateComponents * holidayDateComponents = [[NSCalendar currentCalendar] components:kUnits fromDate:holiday];
if ([components year] == [holidayDateComponents year]
&& [components month] == [holidayDateComponents month]
&& [components day] == [holidayDateComponents day])
{
isHolidayResult = YES;
break;
}
}
return isHolidayResult;
}
и:
NSDate * ensureDateIsntHoliday(NSDate * date, NSArray * holidays)
{
while (isHoliday(date, holidays))
{
// Add one day to the date:
date = addDaysToDate(date, 1);
}
return date;
}
И, наконец, внесите некоторые изменения в нашу функцию сложения, чтобы учесть праздники:
NSDate * addBusinessDaysToDate(NSDate * start, int daysToAdvance, NSArray * holidays)
{
NSDate * end = start;
for (int i = 0; i < daysToAdvance; i++)
{
// If the current date is a weekend, advance:
end = ensureDateIsWeekday(end);
// If the current date is a holiday, advance:
end = ensureDateIsntHoliday(end, holidays);
// And move the date forward by one day:
end = addDaysToDate(end, 1);
}
// Finally, make sure we didn't end on a weekend or a holiday:
end = ensureDateIsWeekday(end);
end = ensureDateIsntHoliday(end, holidays);
return end;
}
Попробуйте и попробуйте:
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDate * start = [NSDate date];
int daysToAdvance = 10;
NSMutableArray * holidays = [[NSMutableArray alloc] init];
[holidays addObject:addDaysToDate(start, 2)];
[holidays addObject:addDaysToDate(start, 3)];
NSDate * end = addBusinessDaysToDate(start, daysToAdvance, holidays);
[holidays release];
NSLog(@"Result: %@", [end descriptionWithCalendarFormat:@"%Y-%m-%d"
timeZone:nil
locale:nil]);
[pool drain];
return 0;
}
Если вы хотите весь проект, вот вам: http://snipt.org/xolnl