首页 文章

NSCalendar第一天的第一天

提问于
浏览
43

有没有人知道是否有办法在NSCalendar上设置一周的第一天,或者是否有一个日历已经将星期一作为一周的第一天而不是星期日 . 我目前正在开发一款基于一周工作量的应用程序,它需要在星期一而不是星期天开始 . 我很可能会做一些工作来解决这个问题,但会有很多极端情况 . 我更喜欢平台为我做这件事 .

提前致谢

这是我正在使用的一些代码 . 现在是星期六,所以我希望工作日是6而不是7,这意味着星期日将是7而不是0到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 回答

  • 0

    我看到其他消息中的误解 . 第一个工作日,以它为准,数字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;
    
  • 77

    Edit: 这不会检查上周开始的前一个月的边缘情况 . 一些更新的代码来涵盖这个:https://stackoverflow.com/a/14688780/308315


    如果有人仍然关注这个,你需要使用

    ordinalityOfUnit:inUnit:forDate:
    

    并将firstWeekday设为2.(1 == Sunday和7 == Saturday)

    这是代码:

    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,而不是零 .

    Documentation link .

  • 8

    此代码构造一个设置为当前周的星期一的日期:

    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
    NSDate *today = [NSDate date];
    NSDate *beginningOfWeek = nil;
    BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                    interval:NULL forDate: today];
    
  • 0

    _C43066_在NSCalendar对象上 . 设置接收器的第一个工作日的索引 .

    - (void)setFirstWeekday:(NSUInteger)weekday
    

    应该做的伎俩 .

  • 1

    在我看来,根据用户区域设置,此设置应该是动态的 . 因此,应该使用:

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

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

  • 3

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

    这是一个适合我的答案:

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

    正如@vikingosegundo指出的那样(elsewhere),一般来说最好让当地人确定哪一天是本周的开始,但是在这种情况下,OP要求本周的开始时间在周一发生,因此我们复制系统日历,并覆盖firstWeekDay .

  • 0

    Kris回答的问题是本周初在上个月开始的边缘情况 . 这是一些更简单的代码,它还检查边缘情况:

    // 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
    
  • 0

    下面还介绍了边缘情况,

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

    试试这个:

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

    我找到了使用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
    

    因为我在2010年11月2日运行了这个程序,你将根据当前日期获得所需的输出 .

    同样,如果你想获得一周的第一个工作日,即星期一的日期,那么只需修改一下代码:

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

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

    获得星期一的那个星期的日期..

    类似地,你可以通过改变整数-1,-2等来尝试找到七个工作日中任何一个的日期......

    希望你的问题得到解答..

    谢谢,Bonson Dias

  • 10

    我这样做的简单方法是让星期一= 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
    
  • 17

    默认情况下,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
        }
    }
    
  • 12

    您只需更改日历的 .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]];
    
  • 0

    ...是否有一个日历已经周一作为一周的第一天,而不是周日 .

    Someday, there will be.

相关问题