11

NSDateComponentsに分解することにより、NSDateから時間と秒のコンポーネントを抽出するメソッドがあります。私のコードは次のとおりです...

unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:travelDate];
NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];

私の問題は、変換で 1 時間を失っていることです。タイムゾーンが原因ではないかと疑っていますが、渡された日付と使用されているカレンダーの両方がGMTであることがわかります。

たとえば、次の NSDate オブジェクトを渡すと (これは [NSDate の説明] のログです)...

2010-08-02 08:00:00 +0100

時間の場合は 8、分の場合は 0 になると思いますが、実際には時間の場合は 7 になります。

私のシステム時間は GMT であるため、上記の NSDate は現在、英国の夏時間で +0100 です。

4

3 に答える 3

15

また、NSDateオブジェクトは常にGMTに従って時刻を表示しますが、その日付からプルするコンポーネントはtimeZoneWithNameパーツによって変更されることに注意してください。

例:

NSDate *today = [NSDate date];
NSLog(@"Today's date: %@",today);

unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:today];
NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];

NSLog(@"Calendar: %@",calendar);
NSLog(@"Travel Components: %@",travelDateTimeComponents);
NSLog(@"Hours: %@",hours);
NSLog(@"Minutes: %@",minutes);

コンソール出力:

[Session started at 2011-01-23 12:59:17 -0700.]
2011-01-23 12:59:19.755 testttt[5697:207] Today's date: 2011-01-23 19:59:19 +0000
2011-01-23 12:59:19.756 testttt[5697:207] Calendar: <__NSCFCalendar: 0x4b2ca70>
2011-01-23 12:59:19.757 testttt[5697:207] Travel Components: <NSDateComponents: 0x4b2de20>
2011-01-23 12:59:19.757 testttt[5697:207] Hours: 19
2011-01-23 12:59:19.758 testttt[5697:207] Minutes: 59

タイムゾーンを変更すると...

NSDate *today = [NSDate date];
NSLog(@"Today's date: %@",today);

unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:@"MST"]];
NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:today];
NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];

NSLog(@"Calendar: %@",calendar);
NSLog(@"Travel Components: %@",travelDateTimeComponents);
NSLog(@"Hours: %@",hours);
NSLog(@"Minutes: %@",minutes);

出力:

2011-01-23 13:05:29.896 testttt[5723:207] Today's date: 2011-01-23 20:05:29 +0000
2011-01-23 13:05:29.897 testttt[5723:207] Calendar: <__NSCFCalendar: 0x4e10020>
2011-01-23 13:05:29.897 testttt[5723:207] Travel Components: <NSDateComponents: 0x4e0f6d0>
2011-01-23 13:05:29.898 testttt[5723:207] Hours: 13
2011-01-23 13:05:29.898 testttt[5723:207] Minutes: 05

現地の時間と分がどのように変化するかに注意してください。ただし、「今日の日付:」の部分は依然としてGMTを反映しています。あなたが私に尋ねれば、プログラマーには少し誤解を招きます。

于 2011-01-23T20:09:21.743 に答える
5

問題は、GMT が英国のサマータイムと等しくないということです。日付2010-08-02 08:00:00 +0100は等しい2010-08-02 07:00:00 GMTので、予想される結果は 7 時間です。

于 2011-01-23T12:47:09.687 に答える
4

アクアさんに同意。それは非常に誤解を招くものであり、画面に頭をぶつけて何日も過ごしました. [NSDate date] は常に現在の日付を返します。上記の例では、2010-08-02 08:00:00 になります。NSDateComponents に変換すると、実際の時間が失われ、タイム ゾーンを保持しない一連の整数 (時間、年など) に変換されます。

NSDate オブジェクトに変換し直すと、年、月、日などの値が取得され、GMT に相対的な値が返されるため、時間が失われます。枠組みで決めた通りです。私がすることは次のとおりです。

+(NSDateComponents *)getComponentFromDate:(NSDate *)date {

    NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

    unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit;
    NSDateComponents* components = [gregorian components:unitFlags fromDate:date];

    NSTimeZone* timeZone = [NSTimeZone localTimeZone];
    if(timeZone.isDaylightSavingTime) components.hour = ((int)timeZone.daylightSavingTimeOffset/3600);

    [gregorian release];

    return components;
}

これにより、日付を取得するためにカレンダーに渡されると、引数として渡された日付の日に常に 00:00:00 に設定される、現在の日に丸められたコンポーネントの「修正された」バージョンが得られます。

于 2011-09-14T13:15:16.000 に答える