2009-07-09 106 views
39

有誰知道是否有辦法在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; 
+0

那麼你有沒有發現任何解決辦法了嗎?我也同樣感到震驚! – 2010-10-04 11:59:51

+0

默認情況下,ISO 8601日曆的第一個工作日設置爲星期一。 – 2014-07-25 13:53:34

回答

12

setFirstWeekday:在NSCalendar對象。 設置接收者的第一個工作日的索引。

- (void)setFirstWeekday:(NSUInteger)weekday 

應該這樣做。

+0

我試着將此值設置爲各種值,並且它對NSCalendary的weekday屬性沒有影響。我在原始文章中添加了一些代碼,以便您可以看到我在做什麼。 謝謝 – Joshua 2009-07-12 05:37:20

+0

對不起,我的意思是NSDateComponents的工作日財產 – Joshua 2009-07-12 05:40:57

+0

這應該有更多的選票 – 2013-06-30 13:23:54

0

試試這個:

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

它應該是`setFirstWeekday:2`爲星期一 – 2014-07-25 13:44:54

3

我看到其他消息的誤解。第一個週日,無論它是,有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; 
17

此代碼構造被設置爲週一的日期本週:

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

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

這一個(與mmc的回答考慮到)實際工作。 – hoha 2011-03-18 10:20:38

+0

如果Joshua先生在這裏提供了答案檢查,本來會很好,因爲它確實是問題描述的內容。 – epologee 2011-05-30 22:22:51

+1

-1因爲這實際上設置開始的時間到週日上午12點。 – joshrl 2012-07-05 17:01:47

0

四中走出來顯示使用nscalender..using下面的代碼中的任何工作日名稱.. 剛剛從Xcode的菜單欄打開控制檯看到results.Copy在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 

,因爲我曾在2010年2月11日運行此程序U將得到所需的輸出去等待當前日期。

同樣,如果你想得到我第一週的第一個工作日。Ë週一的日期,那麼只需修改一下代碼:

CHANGE:[components setDay:([components day]-([components weekday]-1))];

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

獲得該周星期一日期..

同樣ü可以嘗試找到日期七個工作日中的任何一個通過更改整數-1,-2等...

希望你的問題得到解答..

謝謝, Bonson Dias

+0

我想過這個解決方案,但它不能正常工作。對於2001-01-02星期日,它將於2011-01-03星期一返回,但它應該在2010-12-27星期一返回。 – hoha 2011-03-18 09:25:01

10

我認爲這應該是根據用戶區域設置動態。 因此應該使用:

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

這將導致日曆自動根據用戶區域設置的第一個工作日。除非您爲特定目的/用戶區域設置開發應用程序(或者更願意允許用戶選擇這一天)。

+1

+1 - 這實際上是一個個人喜好的問題 - 儘管世界上大部分地區都將星期一作爲一週的開始(實際上它是ISO標準),來自美國,我習慣於星期天的開始。爲什麼不使用這個優雅的答案,並回到用戶自己的日曆設置?這個解決方案對我的應用程序非常有效。 – Jim 2011-10-17 20:44:58

77

編輯:這不檢查星期開始在上個月的邊緣情況。一些更新的代碼來覆蓋這一點: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); 

記住下,W的序eekdays從1開始爲一週的第一天,而不是零。

Documentation link

7

克里斯的答案的問題是一週的開始在前一個月開始的邊緣情況。下面是一些比較容易的代碼,它還會檢查邊緣情況:

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

我已經做到了這個樣子。

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

更新:通過@vikingosegundo

正如指出的(elsewhere),一般最好讓當地確定哪一天是本週開始,但是在這種情況下,OP要求星期一發生一週,因此我們複製系統日曆並覆蓋第一個週日。

0

我這樣做的簡單的方法是讓星期一= 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 
1

下面還覆蓋邊緣的情況下,

- (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

的ISO 8601日曆似乎有它的第一個工作日默認設置爲星期一。

0

使用日曆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 
    } 
} 
0

你可以只改變日曆.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]];