NSCalendarに週の最初の日を設定する方法があるかどうか、または日曜日ではなく月曜日がすでに週の最初の日であるカレンダーがあるかどうか、誰もが知っていますか。現在、約1週間分の作業に基づいたアプリを開発していますが、日曜日ではなく月曜日に開始する必要があります。私はこれを回避するためにいくつかの作業を行うことができますが、多くのコーナーケースがあります。プラットフォームが私のためにそれをすることを望みます。
前もって感謝します
私が使用しているコードは次のとおりです。今は土曜日ですので、平日は7ではなく6になります。つまり、日曜日は0にロールオーバーする代わりに7になるということです。
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;
Edit:これは、週の始まりが前月に始まるEdgeケースをチェックしません。これをカバーするために更新されたコード: 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から始まります。
このコードは、現在の週の月曜日に設定される日付を構成します。
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *today = [NSDate date];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek
interval:NULL forDate: today];
setFirstWeekday: NSCalendarオブジェクト。受信者の最初の平日のインデックスを設定します。
- (void)setFirstWeekday:(NSUInteger)weekday
トリックを行う必要があります。
私の意見では、この設定はユーザーのロケールに応じて動的でなければなりません。したがって、以下を使用する必要があります。
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian setLocale:[NSLocale currentLocale]];
これにより、カレンダーはユーザーロケールに従って最初の週の日を自動的に設定します。特定の目的/ユーザーロケール用にアプリを開発している場合(またはユーザーがこの日を選択できるようにする場合を除く)。
私はこのようにしました。
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は週の始まりを要求していました月曜日に発生するため、システムカレンダーをコピーし、firstWeekDayをオーバーライドします。
クリスの答えの問題は、週の始まりが前月に始まるエッジの場合です。簡単なコードをいくつか紹介し、Edgeのケースもチェックします。
// 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];
}
他のメッセージに誤解があります。最初の平日は、0ではなく1です。デフォルトでは、「Cocoaの日付と時刻のプログラミングガイド:暦計算」のように日曜日= 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;
以下もエッジケースをカバーしています、
- (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];
}
Ivは、次のコードを使用して、nscalender ..を使用して曜日名を表示する方法を見つけました。結果を確認するには、xcodeメニューバーからコンソールを開きます。
_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日にこのプログラムを実行していたので、現在の日付に応じて目的の出力が得られます。
同様に、週の最初の就業日、つまり月曜日の日付を取得したい場合は、コードを少し変更します:
変更:[components setDay:([components day]-([components weekday]-1))];
TO [components setDay:([components day]-([components weekday]-2))];
その週の月曜日の日付を取得します。
同様に、整数-1、-2などを変更することにより、7つの就業日のいずれかの日付を見つけようとすることができます...
あなたの質問に答えられることを願っています。
ありがとう、ボンソン・ディアス
これを行う簡単な方法は、月曜日= 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
これを試して:
NSCalendar *yourCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]
[yourCal setFirstWeekday:0];
Swiftソリューション(注、.yearではなく。yearForWeekOfYearを使用):
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
ISO 8601カレンダーでは、デフォルトで最初の平日が月曜日に設定されているようです。
カレンダーの.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]];
カレンダーの使用 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
}
}