NSCalendar一周中的第一天

问题描述:

有谁知道是否有办法在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

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

试试这个:

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

它应该是`setFirstWeekday:2`为星期一 – 2014-07-25 13:44:54

...有没有已经有星期一作为一周的第一天,而不是周日的日历。

Someday, there will be.

我看到其他消息的误解。第一个周日,无论它是,有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; 

此代码构造被设置为周一的日期本周:

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

四中走出来显示使用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

我认为这应该是根据用户区域设置动态。 因此应该使用:

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

这将导致日历自动根据用户区域设置的第一个工作日。除非您为特定目的/用户区域设置开发应用程序(或者更愿意允许用户选择这一天)。

+1

+1 - 这实际上是一个个人喜好的问题 - 尽管世界上大部分地区都将星期一作为一周的开始(实际上它是ISO标准),来自美国,我习惯于星期天的开始。为什么不使用这个优雅的答案,并回到用户自己的日历设置?这个解决方案对我的应用程序非常有效。 – Jim 2011-10-17 20:44:58

编辑:这不检查星期开始在上个月的边缘情况。一些更新的代码来覆盖这一点:https://*.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

克里斯的答案的问题是一周的开始在前一个月开始的边缘情况。下面是一些比较容易的代码,它还会检查边缘情况:

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

我已经做到了这个样子。

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 

我在这里遇到了很多问题。 。也许它只是我。 。

下面是对我工作的一个答案:

- (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,星期日= 6:

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

下面还覆盖边缘的情况下,

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

的ISO 8601日历似乎有它的第一个工作日默认设置为星期一。

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

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