我仍然是iOS的新手,并且与NSDate有点挣扎。基本上我在我的应用程序中有一些CostPeriods:
CostPeriodDaily
CostPeriodWeekly
CostPeriodMonthly
CostPeriodSemiAnnually
CostPeriodAnnually
根据CostPeriod,我想要特定时期的开始和结束日期。 CostPeriodDaily当然是来自(即今天)16.Feb 2014 00:00:00(当地时间) - 16.Feb 2014 23:59:59(当地时间)。每月将从01.Feb 2014 00:00:00 - 28.Feb 2014 23:59:59等。
我首先提出两个具体问题:
现在到我的endDate函数,还有两个问题: - )
+(NSDate *)endDateForCurrentCostPeriod:(CostPeriod)costPeriod { NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todayComponents =
[gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit ) fromDate:[NSDate date]];
NSRange daysOfCurrentMonth = [gregorian rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]];
NSDateComponents *endDateComponents = [[NSDateComponents alloc] init];
switch (costPeriod) {
case CostPeriodDaily:
[endDateComponents setDay:[todayComponents day]];
[endDateComponents setMonth:[todayComponents month]];
[endDateComponents setYear:[todayComponents year]];
break;
case CostPeriodWeekly:
//Weekday 1 = sunday, 2 = monday
if([todayComponents weekday] == 1){
//Sunday -> do nothing, we have the end date
[endDateComponents setDay:[todayComponents day]];
[endDateComponents setMonth:[todayComponents month]];
[endDateComponents setYear:[todayComponents year]];
} else {
// all other days of current week, so 8- weekday (if Friday: 8 - 6 = + 2 -> Sunday)
NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init];
[componentsToAdd setDay: 8 - [todayComponents weekday]];
NSDate *endOfWeek = [gregorian dateByAddingComponents:componentsToAdd
toDate:[NSDate date] options:0];
NSDateComponents *endOfWeekComponents = [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:endOfWeek];
[endDateComponents setDay:[endOfWeekComponents day]];
[endDateComponents setMonth:[endOfWeekComponents month]];
[endDateComponents setYear:[endOfWeekComponents year]];
}
break;
case CostPeriodMonthly:
[endDateComponents setDay:daysOfCurrentMonth.length];
[endDateComponents setMonth:[todayComponents month]];
[endDateComponents setYear:[todayComponents year]];
break;
case CostPeriodSemiAnnually:
[endDateComponents setYear:[todayComponents year]];
if([todayComponents month] <= 6){
[endDateComponents setDay:30];
[endDateComponents setMonth:6];
} else {
[endDateComponents setDay:31];
[endDateComponents setMonth:12];
}
break;
case CostPeriodAnnually:
[endDateComponents setDay:31];
[endDateComponents setMonth:12];
[endDateComponents setYear:[todayComponents year]];
break;
default:
[endDateComponents setDay:daysOfCurrentMonth.length];
[endDateComponents setMonth:[todayComponents month]];
[endDateComponents setYear:[todayComponents year]];
break;
}
NSDate *endDate = [gregorian dateFromComponents:endDateComponents];
return endDate;
}
答案 0 :(得分:2)
NSWeekdayCalendarUnit:总是1周日和7周六?无论设置什么语言环境?
这是正确的。但这并不意味着1 =星期天总是被认为是本周的第一天。 NSCalendar
有firstWeekDay
方法,
是依赖于语言环境的。 (例如,在德国星期一是一周的第一天。)
如果我NSLog我的endDate(如下面的代码)或开始日期 因为我住在时区,通常是日期和23:00:00 GMT + 1。这是对的吗?
这是正确的。
这个功能一般都可以,或者我会遇到一些问题 取决于具体的区域设置?
你的方法看起来过于复杂。要确定一段时间,你可以使用
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *startOfPeriod, *endOfPeriod;
NSTimeInterval lengthOfPeriod;
NSCalendarUnit unit = NSDayCalendarUnit; // or NSWeekCalendarUnit, NSMonthCalendarUnit, ...
[cal rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:now];
endOfPeriod = [startOfPeriod dateByAddingTimeInterval:lengthOfPeriod]
根据您的语言环境,这应该可以正常工作。对于今天的这一周 (德国,2月16日星期日)将在结果中给出结果
startOfPeriod = 2014-02-10 00:00:00 CET
endOfPeriod = 2014-02-17 00:00:00 CET
因为星期一在星期一开始。 (所以实际上endOfPeriod
不是结束
期间,但是下一期的开始。)
半年度期
没有相应的NSCalendarUnit
,因此您可以按以下步骤操作:
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
// Compute start and end of the current year (as above):
NSDate *startOfYear, *endOfYear;
NSTimeInterval lengthOfYear;
NSCalendarUnit unit = NSYearCalendarUnit;
[cal rangeOfUnit:unit startDate:&startOfYear interval:&lengthOfYear forDate:now];
endOfYear = [startOfYear dateByAddingTimeInterval:lengthOfYear];
// Compute middle of the year:
NSDateComponents *halfYear = [[NSDateComponents alloc] init];
NSRange range = [cal rangeOfUnit:NSMonthCalendarUnit inUnit:NSYearCalendarUnit forDate:now];
halfYear.month = range.length/2;
NSDate *middleOfYear = [cal dateByAddingComponents:halfYear toDate:startOfYear options:0];
// Compare current date with middle of the year and set start/end of period:
NSDate *startOfPeriod, *endOfPeriod;
if ([now compare:middleOfYear] == NSOrderedAscending) {
startOfPeriod = startOfYear;
endOfPeriod = middleOfYear;
} else {
startOfPeriod = middleOfYear;
endOfPeriod = endOfYear;
}
编辑:在马丁的帮助下改变了一切。工作,但仍然混淆结束日期+ 1天+1小时的必要性......
+ (NSDate *)startDateForCostPeriod:(CostPeriod)costPeriod withDate:(NSDate *)date
{
NSCalendar *calender = [NSCalendar currentCalendar];
NSDate *startOfPeriod;
NSTimeInterval lengthOfPeriod;
//If unit is not initialized here, semi annual throws always a caution message since no unit is initialized there
NSCalendarUnit unit = NSMonthCalendarUnit;
//For the SemiAnnual period we need date components
NSDateComponents *todayComponents =
[calender components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit ) fromDate:date];
NSDateComponents *startDateComponents = [[NSDateComponents alloc] init];
switch (costPeriod) {
case CostPeriodDaily:
unit = NSDayCalendarUnit;
break;
case CostPeriodWeekly:
unit = NSWeekCalendarUnit;
break;
case CostPeriodMonthly:
unit = NSMonthCalendarUnit;
break;
case CostPeriodSemiAnnually:
[startDateComponents setDay:1];
[startDateComponents setYear:[todayComponents year]];
if([todayComponents month] <= 6){
[startDateComponents setMonth:1];
} else {
[startDateComponents setMonth:7];
}
break;
case CostPeriodAnnually:
unit = NSYearCalendarUnit;
break;
default:
unit = NSMonthCalendarUnit;
break;
}
if(costPeriod != CostPeriodSemiAnnually){
[calender rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:date];
return startOfPeriod;
} else {
return [calender dateFromComponents:startDateComponents];
}
}
+ (NSDate *)endDateForCostPeriod:(CostPeriod)costPeriod withDate:(NSDate *)date
{
NSCalendar *calender = [NSCalendar currentCalendar];
NSDate *startOfPeriod;
NSTimeInterval lengthOfPeriod;
//If unit is not initialized here, semi annual throws always a caution message since no unit is initialized there
NSCalendarUnit unit = NSMonthCalendarUnit;
//For the SemiAnnual period we need date components
NSDateComponents *todayComponents =
[calender components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit ) fromDate:date];
NSDateComponents *endDateComponents = [[NSDateComponents alloc] init];
switch (costPeriod) {
case CostPeriodDaily:
unit = NSDayCalendarUnit;
break;
case CostPeriodWeekly:
unit = NSWeekCalendarUnit;
break;
case CostPeriodMonthly:
unit = NSMonthCalendarUnit;
break;
case CostPeriodSemiAnnually:
[endDateComponents setYear:[todayComponents year]];
if([todayComponents month] <= 6){
[endDateComponents setDay:30];
[endDateComponents setMonth:6];
} else {
[endDateComponents setDay:31];
[endDateComponents setMonth:12];
}
break;
case CostPeriodAnnually:
unit = NSYearCalendarUnit;
break;
default:
unit = NSMonthCalendarUnit;
break;
}
if(costPeriod != CostPeriodSemiAnnually){
[calender rangeOfUnit:unit startDate:&startOfPeriod interval:&lengthOfPeriod forDate:date];
return [startOfPeriod dateByAddingTimeInterval:lengthOfPeriod];
} else {
//somehow if you take the date without a time it is always 1 day and 1 hour before. i.e. 16.2.2014 is 15.2.2014 22:00:00
//thats why you need to add 1 day and 1 hour!
NSDate *endDate = [calender dateFromComponents:endDateComponents];
NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init];
[componentsToAdd setDay: 1];
[componentsToAdd setHour: 1];
endDate = [calender dateByAddingComponents:componentsToAdd
toDate:endDate options:0];
return endDate;
}
}