NSDate:正确的工作方式与一天中的时间?

时间:2010-11-02 19:55:31

标签: cocoa cocoa-touch time nsdate

我正在使用指定时间的日程安排,例如上午10:30。但是,我不知道日期。我将这些值存储在NSDictionary中,并希望以直接的方式处理它们。

我无法使用NSDate,因为我没有约会。至少,不是直截了当的。

另一种显而易见的方式是NSTimeInterval,但看起来它可能是非常微妙的错误的来源。我特别想到夏令时(由于某些原因,本周我会想到这一点!)。

除此之外,唯一真正想到的是将其保留在格式化字符串中或将其编码为NSNumber(如hours * 60 + minutes)。当然,这两种情况都会很好,但看起来我正在发明一个方形轮,我确信它已经在某个地方已经圆了。

使用Cocoa处理原始时间的方法最少?

3 个答案:

答案 0 :(得分:2)

简短的回答是,没有用于存储时间的内置机制,因此只需使用对您来说最方便的内容。我过去使用自己的编码和解析代码来使用字符串(例如,“22:00”)因为它们易于阅读和调试,但是按照你的建议存储午夜或分钟数并没有错。请记住,你必须自己做数学。

如果你这样做,你将需要单独的年,月,日,小时,分钟和秒值,这样你就可以使用NSCalendar的-dateFromComponents:方法从NSDateComponents构建NSDate。

正如其他人所说,你不能通过小时和分钟添加到现有NSDate来设置时间,因为如果你越过DST边界,你将无法获得你期望的价值。 (但是,我假设您仍然可以添加日期和月份组件而不必担心DST)

答案 1 :(得分:2)

所以,我想没有简单的内置方法可以做到这一点。它看起来像是让Cocoa在DST边界上建立时间的唯一方法是使用字符串。

所以对于后人来说,看起来我会用这样的东西。

测试工具:

//
//  TimeTest.m
//

#import <Foundation/Foundation.h>

#import "Utility.h"

id utility;

void testTime( NSTimeInterval time ) {
    id gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];

    id oneDay = [[[NSDateComponents alloc] init] autorelease];
    [oneDay setDay: 1];

    id thisDay = [gregorian dateFromComponents: [gregorian components: (NSEraCalendarUnit | NSYearCalendarUnit)
                                                             fromDate: [NSDate date]]];
    for (NSInteger dayIdx = 0; dayIdx < 365; ++dayIdx ) {
        NSDate *dateTime = [utility timeInSeconds: time
                                           onDate: thisDay];
        NSLog( @"%@", dateTime );

        thisDay = [gregorian dateByAddingComponents: oneDay
                                             toDate: thisDay
                                            options: 0];
    }
}



int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    utility = [[[Utility alloc] init] autorelease];

    testTime( ((10 * 60.0) + 0.0) * 60.0 );
    testTime( ((9 * 60.0) + 30.0) * 60.0 );

    [pool drain];
    return 0;
}

实用程序标题:

//
//  Utility.h
//

#import <Foundation/Foundation.h>


@interface Utility : NSObject {
    NSCalendar *gregorian;
    NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
}

- (NSDate *)timeInHours: (NSInteger)hours
                minutes: (NSInteger)minutes
                seconds: (NSInteger)seconds
                 onDate: (NSDate *)inDate;

- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
                   onDate: (NSDate *)inDate;

@end

实用程序实现:

//
//  Utility.m
//

#import "Utility.h"


@interface Utility()
@property (nonatomic, readwrite, retain) NSCalendar *gregorian;
@property (nonatomic, readwrite, retain) NSDateFormatter *dateWithoutTimeFormatter, *dateWithTimeFormatter;
@end



@implementation Utility



@synthesize gregorian, dateWithoutTimeFormatter, dateWithTimeFormatter;



- (NSDate *)timeInHours: (NSInteger)hours
                minutes: (NSInteger)minutes
                seconds: (NSInteger)seconds
                 onDate: (NSDate *)inDate;
{
    id timeStr = [[NSMutableString alloc] initWithFormat: @"%02d:%02d:%02d", hours, minutes, seconds];
    id dateStr = [dateWithoutTimeFormatter stringFromDate: inDate];
    id dateTimeStr = [[NSString alloc] initWithFormat: @"%@ %@", dateStr, timeStr];
    [timeStr release];
    id dateTime = [dateWithTimeFormatter dateFromString: dateTimeStr];
    [dateTimeStr release];
    return dateTime;
}



- (NSDate *)timeInSeconds: (NSTimeInterval)inTime
                   onDate: (NSDate *)inDate;
{
    NSAssert1( inTime < 24.0 * 3600.0, @"Time %f must be less than 24hrs", inTime );

    double temp = inTime;
    int hours = rintf(floor( temp / 3600.0 ));
    temp -= ( hours * 3600 );
    int minutes = rintf(floorf( temp / 60.0 ));
    temp -= ( minutes * 60 );
    int seconds = rintf( temp );

    return [self timeInHours: hours
                     minutes: minutes
                     seconds: seconds
                      onDate: inDate];
}



- (id)init;
{
    if (( self = [super init] )) {
        self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];
        self.dateWithoutTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [dateWithoutTimeFormatter setDateFormat: @"yyyy-MM-dd"];
        self.dateWithTimeFormatter = [[[NSDateFormatter alloc] init] autorelease];
        [dateWithTimeFormatter setDateFormat: @"yyyy-MM-dd HH:mm:ss"];
    }
    return self;
}



- (void)dealloc;
{
    self.gregorian = nil;
    self.dateWithoutTimeFormatter = nil;
    self.dateWithTimeFormatter = nil;
    [super dealloc];
}



@end

为什么要为此单独一个单位呢?好吧,我已经写了足够的日期格式代码,知道在飞行中构建NSCalendarNSDateFormatter会彻底杀死性能。

答案 2 :(得分:0)

您可以使用NSDateComponents仅存储所需的组件(例如小时和分钟),然后在需要使用时使用NSCalendar dateByAddingComponents:toDate:options:创建绝对日期参考序列化组件和基准日期。