NSCalendar первый день недели - PullRequest
43 голосов
/ 10 июля 2009

Кто-нибудь знает, есть ли способ установить первый день недели в NSCalendar или есть календарь, в котором уже есть понедельник в качестве первого дня недели вместо воскресенья. В настоящее время я работаю над приложением, в основе которого лежит недельная работа, и оно должно начаться в понедельник, а не в воскресенье. Скорее всего, я могу поработать над этим, но будет много угловых случаев. Я бы предпочел, чтобы платформа сделала это для меня.

Заранее спасибо

Вот код, который я использую. сейчас суббота, так что я надеюсь, что будний день будет 6, а не 7. это будет означать, что воскресенье будет 7 вместо того, чтобы перейти к 0

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setFirstWeekday:0];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit;
NSDateComponents *todaysDate = [gregorian components:unitFlags fromDate:[NSDate date]];
int dayOfWeek = todaysDate.weekday;

Ответы [ 16 ]

77 голосов
/ 12 февраля 2011

Редактировать: Это не проверяет крайний случай, когда начало недели начинается в предыдущем месяце. Некоторый обновленный код, чтобы покрыть это: https://stackoverflow.com/a/14688780/308315


Если кто-то все еще обращает на это внимание, вам нужно использовать

ordinalityOfUnit:inUnit:forDate:

и установите firstWeekday на 2. (1 == Воскресенье и 7 == Суббота)

Вот код:

NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[gregorian setFirstWeekday:2]; // Sunday == 1, Saturday == 7
NSUInteger adjustedWeekdayOrdinal = [gregorian ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:[NSDate date]];
NSLog(@"Adjusted weekday ordinal: %d", adjustedWeekdayOrdinal);

Помните, порядковые номера для рабочих дней начинаются с 1 для первого дня недели, а не с нуля.

Ссылка на документацию .

17 голосов
/ 02 декабря 2009

Этот код создает дату, установленную на понедельник текущей недели:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                interval:NULL forDate: today];
12 голосов
/ 10 июля 2009

setFirstWeekday: для объекта NSCalendar. Устанавливает индекс первого дня недели для получателя.

- (void)setFirstWeekday:(NSUInteger)weekday

Должен сделать трюк.

10 голосов
/ 06 сентября 2010

На мой взгляд, эти настройки должны быть динамическими в зависимости от локали пользователя. Поэтому следует использовать:

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];

Это приведет к тому, что календарь автоматически установит первый день недели в соответствии с языком пользователя. Если вы не разрабатываете свое приложение для конкретной цели / языкового стандарта пользователя (или предпочитаете позволить пользователю выбирать этот день).

8 голосов
/ 23 июня 2013

У меня были проблемы со многими ответами здесь. , возможно это был только я. ,

Вот ответ, который работает для меня:

- (NSDate*)firstDayOfWeek
{
    NSCalendar* cal = [[NSCalendar currentCalendar] copy];
    [cal setFirstWeekday:2]; //Override locale to make week start on Monday
    NSDate* startOfTheWeek;
    NSTimeInterval interval;
    [cal rangeOfUnit:NSWeekCalendarUnit startDate:&startOfTheWeek interval:&interval forDate:self];
    return startOfTheWeek;
}

- (NSDate*)lastDayOfWeek
{
    NSCalendar* cal = [[NSCalendar currentCalendar] copy];
    [cal setFirstWeekday:2]; //Override locale to make week start on Monday
    NSDate* startOfTheWeek;
    NSTimeInterval interval;
    [cal rangeOfUnit:NSWeekCalendarUnit startDate:&startOfTheWeek interval:&interval forDate:self];
    return [startOfTheWeek dateByAddingTimeInterval:interval - 1];
}

Обновление:

Как указал ( в другом месте ) @vikingosegundo, в общем, лучше всего позволить местным жителям определять, какой день является началом недели, однако в этом случае ФП запрашивал начало неделя наступит в понедельник, поэтому мы копируем системный календарь и переопределяем firstWeekDay.

8 голосов
/ 08 апреля 2013

Я сделал это так.

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *today = [NSDate date];
NSDateComponents *compForWeekday = [gregorian components:(NSWeekdayCalendarUnit) fromDate:today];
NSInteger weekDayAsNumber = [compForWeekday weekday]; // The week day as number but with sunday starting as 1

weekDayAsNumber = ((weekDayAsNumber + 5) % 7) + 1; // Transforming so that monday = 1 and sunday = 7
7 голосов
/ 04 февраля 2013

Проблема с ответом Криса - крайний случай, когда начало недели начинается в предыдущем месяце. Вот более простой код, который также проверяет крайний случай:

// Finds the date for the first day of the week
- (NSDate *)getFirstDayOfTheWeekFromDate:(NSDate *)givenDate
{
    NSCalendar *calendar = [NSCalendar currentCalendar];

    // Edge case where beginning of week starts in the prior month
    NSDateComponents *edgeCase = [[NSDateComponents alloc] init];
    [edgeCase setMonth:2];
    [edgeCase setDay:1];
    [edgeCase setYear:2013];
    NSDate *edgeCaseDate = [calendar dateFromComponents:edgeCase];

    NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:edgeCaseDate];
    [components setWeekday:1]; // 1 == Sunday, 7 == Saturday
    [components setWeek:[components week]];

    NSLog(@"Edge case date is %@ and beginning of that week is %@", edgeCaseDate , [calendar dateFromComponents:components]);

    // Find Sunday for the given date
    components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:givenDate];
    [components setWeekday:1]; // 1 == Sunday, 7 == Saturday
    [components setWeek:[components week]];

    NSLog(@"Original date is %@ and beginning of week is %@", givenDate , [calendar dateFromComponents:components]);

    return [calendar dateFromComponents:components];
}
3 голосов
/ 11 ноября 2009

Я вижу непонимание в других сообщениях. Первый день недели, какой бы он ни был, имеет номер 1, а не 0. По умолчанию воскресенье = 1, как в «Руководстве по программированию даты и времени для какао: календарные вычисления»:

"Значение дня недели для воскресенья в григорианском календаре равно 1"

Для понедельника, как первого рабочего дня, единственное средство, которое у меня есть, это условие грубой силы, чтобы исправить расчет

NSCalendar *cal=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [cal components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
// set to 7 if it's Sunday otherwise decrease weekday number
NSInteger weekday=[comps weekday]==1?7:[comps weekday]-1; 
1 голос
/ 19 января 2014

ниже также охватывает край корпуса,

- (NSDate *)getFirstDayOfTheWeekFromDate:(NSDate *)givenDate
{
    NSCalendar *calendar = [NSCalendar currentCalendar];


   NSDateComponents *components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:givenDate];
    [components setWeekday:2]; // 1 == Sunday, 7 == Saturday
    if([[calendar dateFromComponents:components] compare: curDate] == NSOrderedDescending) // if start is later in time than end
    {
        [components setWeek:[components week]-1];
    }

    return [calendar dateFromComponents:components];
}
0 голосов
/ 14 августа 2017

Вы можете просто изменить .firstWeekday календаря.

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.firstWeekday = 2;

Затем используйте rangeOfUnit:startDate:interval:forDate:, чтобы получить первый день

NSDate *startOfWeek;
[calendar rangeOfUnit:NSCalendarUnitWeekOfYear startDate:&startOfWeek interval:nil forDate:[NSdate date]];
...