我希望显示NSDate对象的月数。
//Make Date Six Months In The Future
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *sixMonthsFromNow = [[NSDateComponents alloc] init];
[sixMonthsFromNow setMonth:6];
NSDate *finishDate = [calendar dateByAddingComponents:sixMonthsFromNow toDate:[NSDate date] options:0]; //Six Months Time
//Display
NSCalendarUnit requiredFormat = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *dateComponents = [calendar components:requiredFormat fromDate:[NSDate date] toDate:finishDate options:0];
NSLog(@"%d months %d days %d hours %d minutes %d seconds", [dateComponents month], [dateComponents day], [dateComponents hour], [dateComponents minute], [dateComponents second]);
输出:5 months 29 days 23 hours 59 minutes 59 seconds
哪个好,但我只希望显示月数。
如果我只限制几个月:
//Make Date Six Months In The Future
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *sixMonthsFromNow = [[NSDateComponents alloc] init];
[sixMonthsFromNow setMonth:6];
NSDate *finishDate = [calendar dateByAddingComponents:sixMonthsFromNow toDate:[NSDate date] options:0]; //Six Months Time
//Display
NSCalendarUnit requiredFormat = NSMonthCalendarUnit;
NSDateComponents *dateComponents = [calendar components:requiredFormat fromDate:[NSDate date] toDate:finishDate options:0];
NSLog(@"%d months", [dateComponents month]);
输出:5 months
虽然这在技术上是正确的,但我希望将天数调整为六个月。
有没有简单的方法来达到这个效果?我注意到NSDateComponents上没有舍入属性。我是否必须手动检查天数并决定整理?
我的最终目标是不仅将舍入效果限制为几个月,如果我只提供,则应该可以将小时数限制为几天:NSDayCalendarUnit
答案 0 :(得分:2)
以下方法可以满足您的需求。 这个想法是在计算(向下舍入)数量的日历单位之后 在开始日期和结束日期之间,将该金额和一个金额添加到开始日期 并检查哪一个更接近结束日期:
@interface NSCalendar (MyCategory)
-(NSInteger)roundedUnit:(NSCalendarUnit)unit fromDate:(NSDate *)fromDate toDate:(NSDate *)toDate;
@end
@implementation NSCalendar (MyCategory)
-(NSInteger)roundedUnit:(NSCalendarUnit)unit fromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
// Number of units between the two dates:
NSDateComponents *comps = [self components:unit fromDate:fromDate toDate:toDate options:0];
NSInteger value = [comps valueForComponent:unit];
// Add (value) units to fromDate:
NSDate *date1 = [self dateByAddingComponents:comps toDate:fromDate options:0];
// Add (value + 1) units to fromDate:
[comps setValue:(value + 1) forComponent:unit];
NSDate *date2 = [self dateByAddingComponents:comps toDate:fromDate options:0];
// Now date1 <= toDate < date2. Check which one is closer,
// and return the corresponding value:
NSTimeInterval diff1 = [toDate timeIntervalSinceDate:date1];
NSTimeInterval diff2 = [date2 timeIntervalSinceDate:toDate];
return (diff1 <= diff2 ? value : value + 1);
}
@end
你会用它作为
NSInteger months = [calendar roundedUnit:NSMonthCalendarUnit fromDate:[NSDate date] toDate:finishDate];
代码使用NSDateComponents
的实用程序方法
https://github.com/henrinormak/NSDateComponents-HNExtensions/blob/master/README.md:
- (void)setValue:(NSInteger)value forComponent:(NSCalendarUnit)unit;
- (NSInteger)valueForComponent:(NSCalendarUnit)unit;
这些方法是OS X 10.9中的新增功能,但在iOS 7中不可用。
答案 1 :(得分:0)
正如另一位评论者指出的那样,你两次打电话给NSDate,第二次约会比第一次稍晚。使用相同的日期对象两次,您将不会出现舍入错误。
关于如何舍入:
我认为NSCalendars日历计算方法没有内置任何舍入。
您需要确定这对您意味着什么。你可能会在中途回合。在这种情况下,您可以使用rangeOfUnit:inUnit:forDate方法向日历询问当前月份的天数,然后将该天数的一半添加到结束日期,然后询问月份。如果您只想“在一周内完成整理,那么只需要在结束日期之前添加一周,然后再询问差异数。”
答案 2 :(得分:0)
我遇到了类似的问题:
let fmt1 = NSDateComponentsFormatter()
fmt1.allowedUnits = .CalendarUnitYear |
.CalendarUnitMonth |
.CalendarUnitDay
let dc1 = NSDateComponents()
dc1.month = 1
dc1.day = 15
// This occasionally outputs "1 month, 14 days" instead of
// "1 month, 15 days" when the formatter is constrained to
// years, months and days. If formatter is allowed to use
// all units, the output is "1 month, 14 days, 23 hours,
// 59 minutes, 59 seconds".
fmt1.stringFromDateComponents(dc1)
这可以通过指定正秒数并将其组合来解决
将maximumUnitCount
格式化程序参数设置为固定值:
let fmt2 = NSDateComponentsFormatter()
fmt2.allowedUnits = .CalendarUnitYear |
.CalendarUnitMonth |
.CalendarUnitDay
fmt2.maximumUnitCount = 2
fmt2.collapsesLargestUnit = true
let dc2 = NSDateComponents()
dc2.month = 1
dc2.day = 15
dc2.second = 10
// This always outputs "1 month, 15 days"
fmt2.stringFromDateComponents(dc2)
此修复程序也可能适用于您的情况:只需在调用NSDateComponents
之前为dateByAddingComponents
分配一些正数秒:
[sixMonthsFromNow setMonth: 6];
[sixMonthsFromNow setSecond: 10];