2010-11-02 38 views
3

我正在制定一個時間表,指定一天的時間,例如上午10:30。但是,我不知道日期。我將把它們作爲值存儲在NSDictionary中,並希望以直接的方式處理它們。NSDate:與一天中的時間一起工作的正確方法?

我不能使用NSDate,因爲我沒有日期。至少,不是直截了當的。

看起來很明顯的另一種方法是NSTimeInterval,但看起來它可能是非常微妙的錯誤的來源。我特別想到夏令時(由於某種原因本週在我心中!)。

除此之外,唯一值得思考的事情是將其保存爲格式化字符串或將其編碼在NSNumber(如hours * 60 + minutes)中。當然,這兩種方法都可以解決問題,但似乎我正在發明一個方形車輪,我確信在某個地方已經有了一個方形車輪。

對付使用可可的原始時代的糧食方式,最起碼什麼?

回答

2

簡單的答案是,沒有內置的存儲時間機制,所以只需使用最方便的任何方法即可。過去我使用自己的編碼和解析代碼(例如,「22:00」)使用字符串,因爲它們易於閱讀和調試,但按照您的建議,在午夜之前存儲秒或分鐘沒有任何問題。請記住,你必須自己做數學。您需要單獨的年,月,日,小時,分鐘和秒值,以便您可以使用NSCalendar的-dateFromComponents:方法從NSDateComponents構建NSDate。

正如其他人說,你不能加入小時和分鐘設置時間的日到現有NSDate因爲如果你越過邊界DST你不會得到你所期望的價值。 (不過,我想你仍然可以添加日期和月份組成部分,而不必擔心DST)

0

您可以使用NSDateComponents只存儲(小時和分鐘爲例),你需要的組件,然後用NSCalendardateByAddingComponents:toDate:options:創建一個絕對日期的引用,當你需要使用序列化組件和基礎日期。

+0

不幸的是,這會在調整時鐘的日子返回錯誤的結果。在2010年3月14日上午11:00至上午9點,在2010-11-07上午9點加上十個小時。我大概可以作弊並讓我的時間相對於凌晨4點或其他時間,但是我會對日曆做一個愚蠢的假設。 (iPhone報警錯誤的可能原因?) – 2010-11-02 20:19:37

+0

啊,是的,這似乎是iPhone報警錯誤的可能來源。哦,不過,這值得嘗試。 :-) – 2010-11-02 20:24:08

+0

是的。當一個真正的好主意行不通時,這是非常不方便的。但謝謝你的嘗試。 :) – 2010-11-02 20:29:19

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會徹底殺死性能。