NSCalendar первый день недели

Кто-нибудь знает, есть ли способ установить первый день недели в 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;

Ответ 1

Изменить: Это не проверяет край, где начинается начало недели в предыдущем месяце. Некоторые обновленные коды для этого: fooobar.com/questions/56257/...


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

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 в первый день недели, а не ноль.

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

Ответ 2

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

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

NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                interval:NULL forDate: today];

Ответ 3

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

- (void)setFirstWeekday:(NSUInteger)weekday

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

Ответ 4

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

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

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

Ответ 5

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

// 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];
}

Ответ 6

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

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

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

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

- (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];
}

Update:

Как указано (в другом месте) by @vikingosegundo, в целом лучше всего разрешить местному определять, какой день является началом недели, однако в этом случае OP просил начать неделю в понедельник, поэтому мы копируем системный календарь и переопределяем firstWeekDay.

Ответ 8

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

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

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

NSCalendar *cal=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [cal components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
// set to 7 if it Sunday otherwise decrease weekday number
NSInteger weekday=[comps weekday]==1?7:[comps weekday]-1; 

Ответ 9

Ниже также рассматривается краевой случай,

- (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];
}

Ответ 10

Попробуйте следующее:

NSCalendar *yourCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
[yourCal setFirstWeekday:0];

Ответ 11

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

Когда-нибудь будет.

Ответ 12

Iv выяснил способ отображения любого имени дня недели с помощью nscalender.. используя следующий код.  Просто откройте консоль из строки меню xcode, чтобы увидеть результаты. Копия Вставьте следующий код в свой метод viewDidLoad, чтобы получить первый день недели.

NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MM/dd/yyyy :EEEE"];
NSString *dateString = [dateFormat stringFromDate:today];
NSLog(@"date: %@", dateString);
[dateFormat release];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components = [gregorian components:NSWeekdayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:today];
[components setDay:([components day]-([components weekday]-1))];

NSDate *beginningOfWeek = [gregorian dateFromComponents:components];
NSDateFormatter *dateFormat_first = [[NSDateFormatter alloc] init];
[dateFormat_first setDateFormat:@"MM/dd/yyyy :EEEE"];
NSString *dateString_first = [dateFormat_first stringFromDate:beginningOfWeek];
NSLog(@"First_date: %@", dateString_first);

Выход будет:

 date: 02/11/2010 :Thursday
 First_date: 02/07/2010 :Sunday

так как я запустил эту программу 2/11/2010, u получит желаемый результат в зависимости от текущей даты.

Аналогично, если u хочет получить первый рабочий день недели, то есть в понедельник, а затем немного измените код:

ИЗМЕНИТЬ: [components setDay:([components day]-([components weekday]-1))];

К [components setDay:([components day]-([components weekday]-2))];

чтобы получить дату понедельника на эту неделю.

Аналогично, вы можете попытаться найти дату любого из семи рабочих дней, изменив целое число -1, -2 и так далее...

Надеюсь, что на вопрос ответят.

Спасибо, Bonson Dias

Ответ 13

Мой простой способ сделать это - получить понедельник = 0, воскресенье = 6:

    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
    NSInteger dayNumStartingFromMonday = ([dateComponents weekday] - 2 + 7) % 7;    //normal: Sunday is 1, Monday is 2

Ответ 14

Календар ISO 8601, по-видимому, имеет первый день недели, установленный в понедельник по умолчанию.

Ответ 15

Использование календаря nextWeekend (iOS 10 или новее) и ordinality (спасибо @kris-markel). Я получил понедельник в качестве первой недели для календаря en_US.

Вот пример с возвратом в firstWeekday:

extension Calendar {
    var firstWorkWeekday: Int {
        guard #available(iOS 10.0, *) else{
            return self.firstWeekday
        }
        guard let endOfWeekend = self.nextWeekend(startingAfter: Date())?.end else {
            return self.firstWeekday
        }
        return self.ordinality(of: .weekday, in: .weekOfYear, for: endOfWeekend) ?? self.firstWeekday
    }
}

Ответ 16

Вы можете просто изменить .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]];