44

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

17 回答 17

78

编辑:这不会检查上个月开始的边缘情况。一些更新的代码来涵盖这一点: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 开始,而不是从零开始。

文档链接

于 2011-02-11T22:31:34.330 回答
18

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

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

NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                interval:NULL forDate: today];
于 2009-12-02T20:16:27.697 回答
12

setFirstWeekday:在 NSCalendar 对象上。为接收者设置第一个工作日的索引。

- (void)setFirstWeekday:(NSUInteger)weekday

应该做的伎俩。

于 2009-07-09T23:29:47.630 回答
11

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

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

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

于 2010-09-06T06:03:27.460 回答
9

我已经这样做了。

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
于 2013-04-08T11:10:12.480 回答
8

我在这里的很多答案都遇到了麻烦。. 也许只是我。.

这是一个对我有用的答案:

- (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 所指出的(在其他地方),一般来说,最好让当地人确定哪一天是一周的开始,但是在这种情况下,OP 要求一周的开始发生在星期一,因此我们复制系统日历,并覆盖 firstWeekDay。

于 2013-06-23T10:20:36.093 回答
7

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];
}
于 2013-02-04T14:26:30.267 回答
3

我在其他消息中看到了误解。第一个工作日,无论它是什么,都有数字 1 而不是 0。默认情况下,Sunday=1,如“Cocoa 日期和时间编程指南简介:日历计算”中所示:

“公历中星期日的工作日值为 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; 
于 2009-11-11T18:32:58.350 回答
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];
}
于 2014-01-19T19:01:28.350 回答
1

您可以更改.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]];
于 2017-08-14T07:21:14.960 回答
0

尝试这个:

NSCalendar *yourCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
[yourCal setFirstWeekday:0];
于 2009-07-10T00:09:33.183 回答
0

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 上运行了这个程序,你将根据当前日期获得所需的输出。

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

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

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

获取该周的星期一日期..

同样,您可以尝试通过更改整数-1、-2 等来查找七个工作日中的任何一个的日期...

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

谢谢,邦森迪亚斯

于 2010-02-11T07:29:55.990 回答
0

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

于 2014-07-25T13:53:25.383 回答
0

使用日历nextWeekend(iOS 10 或更高版本)和序数(感谢@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
    }
}
于 2017-07-25T21:11:31.473 回答
0

Swift 解决方案(注意,使用.yearForWeekOfYear,而不是 .year):

let now = Date()
let cal = Calendar.current
var weekComponents = cal.dateComponents([.yearForWeekOfYear, .weekOfYear,
                                         .weekday], from: now)
//weekComponents.weekday = 1  // if your week starts on Sunday
weekComponents.weekday = 2  // if your week starts on Monday
cal.date(from: weekComponents) // returns date with first day of the week
于 2019-08-10T12:00:27.903 回答
-1

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

总有一天,会有的。

于 2009-10-12T10:22:17.293 回答
-1

我这样做的简单方法是让星期一 = 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
于 2013-09-05T09:26:25.520 回答