可靠地检查 NSDate 是不是在给定的小时、天或周内

Posted

技术标签:

【中文标题】可靠地检查 NSDate 是不是在给定的小时、天或周内【英文标题】:Reliably checking whether NSDate falls within given hour, day or week可靠地检查 NSDate 是否在给定的小时、天或周内 【发布时间】:2012-10-19 21:06:55 【问题描述】:

我需要获取存储的 NSDate 并可靠地确定它是否在当前时刻的小时、天或周内。我似乎已经拼凑出一个解决方案,但之前没有解决过这个问题,我不完全相信它是一个可靠的解决方案。

这是否能在用户设置的 12 小时与 24 小时时间内存活下来? the date formatting guide 表示此用户设置可能会导致一些意外的日期行为:“在 ios 中,用户可以覆盖默认的 AM/PM 与 24 小时时间设置。这可能会导致 NSDateFormatter 重写您设置的格式字符串。”

这个问题的基本代码模式怎么样?这段代码似乎可靠地服务于它的目的吗?我讨厌发布“检查我的代码”之类的问题,但这对我来说是一个不熟悉的问题,并且足够棘手,无法进行严格的测试,这似乎是合理的。 NSDateFormatter 对我来说也比较新;这个问题的另一个动机。

注意:我紧张的主要来源是,将日期转换为字符串然后进行字符串比较似乎是解决此问题的固有脆弱方法。但这是我能想到的最好的了。

快速参考:我在这三种情况下使用的dateFormats 分别是:

dateFormat = @"yyyyMMddHH"; // For "this hour" check
dateFormat = @"yyyyMMdd"; // For "today" check
dateFormat = @"yyyyww"; // For "this week" check 

谢谢!代码如下:

- (BOOL)didThisCycle 
    // Case 1: hourly; Case 2: daily; Case 3: weekly
    BOOL did = NO;

    NSDate *now = [NSDate date];
    NSDate *lastDid = [self.didDates lastObject];

    if (![lastDid isKindOfClass:[NSDate class]])  // Crash protection
        return NO;
    

    int type = [self.goalType intValue];
    switch (type) 
        case 1:
        
            // If hourly check hour
            NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
            formatter.dateFormat = @"yyyyMMddHH";
            NSString *nowString = [formatter stringFromDate:now];
            NSString *lastDidString = [formatter stringFromDate:lastDid];
            if ([nowString isEqualToString:lastDidString]) 
                did = YES;
             else 
                did = NO;
            
            break;
        
        case 2:
        
            // If daily check day
            NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
            formatter.dateFormat = @"yyyyMMdd";
            NSString *nowString = [formatter stringFromDate:now];
            NSString *lastDidString = [formatter stringFromDate:lastDid];
            if ([nowString isEqualToString:lastDidString]) 
                did = YES;
             else 
                did = NO;
            
            break;
        
        case 3:
        
            // If weekly check week
            NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
            formatter.dateFormat = @"yyyyww";
            NSString *nowString = [formatter stringFromDate:now];
            NSString *lastDidString = [formatter stringFromDate:lastDid];
            if ([nowString isEqualToString:lastDidString]) 
                did = YES;
             else 
                did = NO;
            
            break;
        
        default:
        
            did = NO;
            break;
        
    

    return did;

【问题讨论】:

“将日期转换为字符串然后进行字符串比较似乎是一种天生脆弱的方法” 嗯,它们不是用户输入的日期。该程序正在存储某些程序事件的日期等。因此,这些日期几乎总是(也总是)在某些事件发生时通过 [NSDate date] 创建。但是问题就变成了如何测试 NSDate 是否在给定的范围内(在这种情况下,是当前的小时、天或周)。例如下午 1:02 发生了一件事情。现在是下午 1:56,所以如果我们每小时检查一次(案例 1),这应该返回 true。在下午 2:01 它应该返回 false 等。 在这种情况下它是初等数学,前提是 NSDate 具有检索日期组件(小时、天、周)的方法。 AFAIK 它有。 【参考方案1】:

使用 NSDateComponents 类,如下所示:

NSDate *someDate = // whatever
NSDate *now = [NSDate date];
NSDateComponents *thenComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:someDate];
NSDateComponents *nowComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:now];
if([thenComponents year] == [nowComponents year] && [thenComponents month] == [nowComponents month] && [thenComponents day] == [nowComponents day] && [thenComponents hour] == [nowComponents hour])

    // hooray

如果您只想查看日期,请删除“小时”组件,或者同时删除“小时”和“日期”(并替换为 NSWeekCalendarUnit-week 方法)以查看星期。

【讨论】:

谢谢诺亚,效果很好。不知道组件的功能。

以上是关于可靠地检查 NSDate 是不是在给定的小时、天或周内的主要内容,如果未能解决你的问题,请参考以下文章

在iOS中将NSdate四舍五入到最近的小时

可靠地确定浮点值向量是不是(数字上)等距

Pandas:时间序列数据:如何选择一小时、一天或一分钟的行?

如何在 Swift 中从 NSDate 获取日、月和小时

如何可靠地检查对象是 EcmaScript 6 Map/Set?

iOS:从 NSDate 获取本地化小时