NSCalendar 一周的第一天

发布于 2024-07-26 19:21:37 字数 646 浏览 12 评论 0原文

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

Does anyone know if there is a way to set the first day of the week on a NSCalendar, or is there a calendar that already has Monday as the first day of the week, instead of Sunday.
I'm currently working on an app that is based around a week's worth of work, and it needs to start on Monday, not Sunday. I can most likely do some work to work around this, but there will be a lot of corner cases. I'd prefer the platform do it for me.

Thanks in advance

Here's some the code that I'm using. it's saturday now, so what I would hope is that weekday would be 6, instead of 7. that would mean that Sunday would be 7 instead of rolling over to 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

假扮的天使 2024-08-02 19:21:38

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

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

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

In my opinion this settings should be dynamic according to the user locale.
Therefore one should use:

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

This will cause the calendar to set the first week day according to the user locale automatically. Unless you are developing your app for a specific purpose/user locale (or prefer to allow the user to choose this day).

蓝海似她心 2024-08-02 19:21:38

我就是这样做的。

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

I've done it like this.

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
故事和酒 2024-08-02 19:21:38

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

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

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

I had trouble with a lot of the answers here. . maybe it was just me. .

Here's an answer that works for me:

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

As pointed out (elsewhere) by @vikingosegundo, in general its best to let the local determine which day is the start of the week, however in this case the OP was asking for the start of the week to occur on Monday, hence we copy the system calendar, and override the firstWeekDay.

感情洁癖 2024-08-02 19:21:38

克里斯的答案的问题在于边缘情况,即一周的开始是从上个月开始的。 这是一些更简单的代码,它还检查边缘情况:

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

The problem with Kris' answer is the edge case where the beginning of the week starts in the prior month. Here's some easier code and it also checks the edge case:

// 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];
}
爱冒险 2024-08-02 19:21:38

我在其他消息中看到了误解。 第一个工作日,无论是哪一个,其数字都是 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; 

I see misunderstanding in the other messages. The first weekday, whichever it is, has number 1 not 0. By default Sunday=1 as in the "Introduction to Date and Time Programming Guide for Cocoa: Calendrical Calculations":

"The weekday value for Sunday in the Gregorian calendar is 1"

For the Monday as a first workday the only remedy I have is brute force condition to fix the calculation

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; 
梦初启 2024-08-02 19:21:38

下面还涵盖了边缘情况,

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

Below also covers the edge case,

- (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];
}
坏尐絯℡ 2024-08-02 19:21:38

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

You can just change .firstWeekday of the calendar.

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.firstWeekday = 2;

Then use rangeOfUnit:startDate:interval:forDate: to get the first day

NSDate *startOfWeek;
[calendar rangeOfUnit:NSCalendarUnitWeekOfYear startDate:&startOfWeek interval:nil forDate:[NSdate date]];
夜光 2024-08-02 19:21:38

尝试这个:

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

Try this:

NSCalendar *yourCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
[yourCal setFirstWeekday:0];
少年亿悲伤 2024-08-02 19:21:38

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 上运行了此程序,所以您将得到所需的输出取决于当前日期。

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

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


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

获取该周的星期一日期。

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

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

谢谢,
邦森迪亚斯

Iv found out the way to display any weekday name using nscalender..using the following code..
Just open your console from xcode menu bar to see the results.Copy Paste the following code in your viewDidLoad method to get the first day of the week

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);

The Output will be:

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

since i had run this program on 2/11/2010 u will get the desired output depending on the current date.

Similarly if u want to get the first working day of the week i.e Monday's date then just modify the code a bit:

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

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

to get Mondays date for that week..

Similarly u can try to find the date of any of seven workdays by changing the integer -1,-2 and so on...

Hope u r question is answered..

Thanks,
Bonson Dias

绅士风度i 2024-08-02 19:21:38

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

The ISO 8601 calendar appears to have it's first weekday set to monday by default.

臻嫒无言 2024-08-02 19:21:38

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

Using the Calendar nextWeekend (iOS 10 or later) and ordinality (thanks @kris-markel). I've gotten Monday as first of the week for the en_US calendar.

Here is an example of it with fallback to 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
    }
}
他不在意 2024-08-02 19:21:38

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

The Swift solution (note, use .yearForWeekOfYear, not .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
情泪▽动烟 2024-08-02 19:21:38

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

总有一天,会有的。

… is there a calendar that already has Monday as the first day of the week, instead of Sunday.

Someday, there will be.

阳光的暖冬 2024-08-02 19:21:38

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

My simple way of doing this is to get Monday = 0, Sunday = 6:

    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
    NSInteger dayNumStartingFromMonday = ([dateComponents weekday] - 2 + 7) % 7;    //normal: Sunday is 1, Monday is 2
囚我心虐我身 2024-08-02 19:21:37

编辑:这不会检查一周的开始于上个月开始的边缘情况。 一些更新的代码来解决这个问题:https://stackoverflow.com/a/14688780/308315


以防有人仍在付款注意这一点,您需要使用

ordinalityOfUnit:inUnit:forDate:

firstWeekday并将其设置为2。(1 == Sunday and 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);

请记住,工作日的序数从一周的第一天开始,而不是零。

文档链接

Edit: This does not check the edge case where the beginning of the week starts in the prior month. Some updated code to cover this: https://stackoverflow.com/a/14688780/308315


In case anyone is still paying attention to this, you need to use

ordinalityOfUnit:inUnit:forDate:

and set firstWeekday to 2. (1 == Sunday and 7 == Saturday)

Here's the code:

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);

Remember, the ordinals for weekdays start at 1 for the first day of the week, not zero.

Documentation link.

岁吢 2024-08-02 19:21:37

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

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

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

This code constructs a date that is set to Monday of the current week:

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

NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
                                interval:NULL forDate: today];
长发绾君心 2024-08-02 19:21:37

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

- (void)setFirstWeekday:(NSUInteger)weekday

应该做到这一点。

setFirstWeekday: on the NSCalendar object.
Sets the index of the first weekday for the receiver.

- (void)setFirstWeekday:(NSUInteger)weekday

Should do the trick.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文