首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSDateComponent舍入

NSDateComponent舍入
EN

Stack Overflow用户
提问于 2014-01-22 12:56:07
回答 3查看 928关注 0票数 3

我希望显示来自NSDate对象的月数。

代码语言:javascript
复制
//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

这很好,但我只想展示几个月的时间。

如果我只限于几个月:

代码语言:javascript
复制
//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,那么它应该能够把几个小时整到几天。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-22 16:02:36

下面的方法可以满足您的需要。这样做的想法是,在计算开始日期和结束日期之间的日历单位(四舍五入)数量后,将该金额和多一个添加到开始日期,并检查哪一个更接近结束日期:

代码语言:javascript
复制
@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

你会把它当作

代码语言:javascript
复制
NSInteger months = [calendar roundedUnit:NSMonthCalendarUnit fromDate:[NSDate date] toDate:finishDate];

代码使用实用程序方法对来自NSDateComponentshttps://github.com/henrinormak/NSDateComponents-HNExtensions/blob/master/README.md

代码语言:javascript
复制
- (void)setValue:(NSInteger)value forComponent:(NSCalendarUnit)unit;
- (NSInteger)valueForComponent:(NSCalendarUnit)unit;

这些方法在OSX10.9中是新的,但在iOS 7中不可用。

票数 2
EN

Stack Overflow用户

发布于 2014-01-22 13:26:46

正如另一位评论者所指出的,您要给NSDate打两次电话,第二次约会稍微晚于第一次约会。使用同一日期对象两次,您将不会得到舍入错误。

至于如何绕过:

我认为在NSCalendars日历计算方法中没有任何四舍五入。

你得决定这对你意味着什么。你可以在半途而废。在这种情况下,您可以使用rangeOfUnit:inUnit:forDate方法询问当前月份中有多少天,然后将一半的天数添加到结束日期,然后询问月份。如果您只想“在一周内进行汇总,那么在询问月差数之前,只在结束日期添加一周”。

票数 0
EN

Stack Overflow用户

发布于 2015-04-29 14:12:14

我也有一个类似的问题:

代码语言:javascript
复制
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格式化程序参数设置为固定值相结合来解决这一问题:

代码语言:javascript
复制
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

代码语言:javascript
复制
[sixMonthsFromNow setMonth: 6];
[sixMonthsFromNow setSecond: 10];
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21283592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档