2010-12-01 49 views
8

我正在编写一个使用核心数据存储我的数据的应用程序。包括在这个日期字段中,我只对日期不感兴趣。 我需要根据日期(不是时间)来选择记录,所以我已经创建了的NSDate类别返回日期,标准化为一组时间如下:NSDate创建没有时间元素的日期的最佳做法

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 
NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:dateTime]; 
NSDate *dateOnly = [[NSCalendar currentCalendar] dateFromComponents:comps]; 
[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

然后我当我将数据添加到核心数据存储(我有一个使用此方法设置原始日期值的setter)时使用此方法,然后使用此方法创建一个日期,用于比较执行提取请求时的日期。所以理论上这应该总是有效的 - 也就是选出我要找的日期。

虽然我不完全确定改变时区或区域设置会产生什么效果,但我略感紧张。它会继续工作吗?

只有当您对时间没有兴趣时,才能在日期上存储和搜索时被认为是最佳实践。

干杯。

编辑

阅读讨论后建议我认为我应该修改我的代码如下。我的想法是,如果我确保将其推送到特定的日历系统和特定的时区(UTC),那么日期应始终保持不变,无论您设置日期和阅读日期时的位置。对这个新代码的任何评论表示赞赏。

+ (NSDate *)dateWithNoTime:(NSDate *)dateTime { 
if(dateTime == nil) { 
    dateTime = [NSDate date]; 
} 

NSCalendar  *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; 
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease]; 
components = [calendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit 
         fromDate:dateTime]; 

NSDate *dateOnly = [calendar dateFromComponents:components]; 

[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];   // Push to Middle of day. 
return dateOnly; 

}

+0

感谢您的解决方案! :d 只是一个小的校正: 线: `[dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];` 应该是: `dateOnly = [dateOnly dateByAddingTimeInterval:(60.0 * 60.0 * 12.0)];` – 2016-03-02 20:01:29

回答

5

你有几个问题需要解决在这里。首先,如你所述,时区。您还需要担心夏令时,这会改变“正午”的概念。

看看CocoaDev上的this discussion,苹果工程师给出一些答案并讨论一些最佳实践。

+0

谢谢你。阅读完讨论后,看起来应该确保我总是使用相同的日历系统和时区进行存储和比较。基于这种新思维,我已经为自己的问题添加了新的代码。 – SimonB 2010-12-01 16:49:39

3

一个更简单的解决方案是使用一个谓词来查找某个范围内的日期。

使用NSCalendarComponent为您创建开始日期和结束日期“day”,然后将其包含在谓词中。

NSPredicate *p=[NSPredicate predicateWithFormat:@"[email protected] <= date <= [email protected]",startDate,endDate]; 

这将提供最大的灵活性,而不会太复杂。日期和时间编程看似复杂。准备好做一些工作。

2

我也结束了一个场景,我需要有一个NSDate来比较日期而不考虑时间。

我有一个过滤器的机制,并作为用户界面的一部分,如果用户今天选择最低日期作为开始日期和结束日期,我会显示“所有时间段”,而不是格式中的字符串:

2006年1月5日 - 24/12/2009

所以,我需要把使用的NSDate+date今天的日期,并将其与结束日期。该结束日期来自UIDatePicker,没有时间,但+date返回了现在的日期和时间。

所以我写了这个简短方便的方法,它收到一个日期对象,使用NSDateComponentsNSCalendar类来提取日,月和年。然后

这些3个参数被用于创建新的NSDate使用NSDateFormatter's - dateFromString:方法,其结果是一个NSDate对应于相同的“日期”(在传统的人力概念)作为参数date但没有时间。

- (NSDate *)strictDateFromDate:(NSDate *)date{ 
    NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; 
    NSDateComponents *components = [[NSCalendar currentCalendar] components:flags 
                    fromDate:[NSDate date]]; 
    NSString *stringDate = [NSString stringWithFormat:@"%d/%d/%d", components.day, components.month, components.year]; 

    NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; 
    formatter.dateFormat = @"dd/MM/yyyy"; 

    return [formatter dateFromString:stringDate]; 
} 

我希望您以后可以使用并享受此功能。

+0

我试过这个,但返回值也包含时间戳! – 2012-11-14 06:49:39

相关问题