4

問題について検索しましたが、関連するヘルプは見つかりませんでした...

ストーリー:ユーザーは名前、開始日、終了日、メモで継続イベントを作成するため、すべてのフィールドがSqliteデータベースに保存されます。両方の日付形式は「yyyy-MM-dd」です。その後、ユーザーがイベントでアクションを実行したい場合、アプリはユーザーが開始日と終了日で選択した日付を確認し、入力された日付が開始日より前か終了日より後かをユーザーに通知します。

問題:私はユーザーとして、2012年8月18日から2012年9月18日までのイベントを作成しました。その後、2012年8月18日にログを記録し、通知を受けました。アプリをデバッグしました。そして私は驚いた。「yyyy-MM-dd」形式の文字列からの日付オブジェクトは「2012-08-1719:30:00+0000」です。コードは次のとおりです。

           #define kPickerDate @"yyyy-MM-dd"
           NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
           [formatter setDateFormat:kPickerDate];
           NSDate *sDate = [formatter dateFromString:start_date]; 
           NSDate *eDate = [formatter dateFromString:exam_date]; 

アプリはどうですか??????????????

4

2 に答える 2

10

anNSDateは日付だけでなく、時刻でもあります。

すべての段階でこれを確認する必要があります。

  • 解析時に日付が正しく作成されていますか? 現地時間の午前 0 時ではなく、UTC の午前 0 時にする必要があります。おそらくこれには aNSDateFormatterを使用しています。タイムゾーンが UTC に設定されていることを確認してください。
  • 日付は SQLite に正しく保存されていますか? 繰り返しますが、UTC として保存していることを確認してください。ただし、正しく解析している場合、これは機能するはずです。
  • 出力を正しくフォーマットしていますか? おそらくNSDateFormatterこれに a を使用しています。タイムゾーンが UTC に設定されていることを確認してください。

3 つの部分がすべて完璧になって初めて、潜在的なバグから解放されます。

日付フォーマッタのタイム ゾーンを設定するには、次を使用します。

formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"];

現地時間を採用してこれを回避しようとしないでください。

現地時間の問題:

  • 多くのタイム ゾーンでは、サマー タイムによって時間が年に数回変わります。この 1 時間の差により、時間の日付部分が前日に繰り越されます。
  • ユーザーが夏時間のないタイム ゾーンにいる場合、別のタイム ゾーンに移動する可能性があります。繰り返しますが、時間の日付部分が 1 日ずれる場合があります。

唯一の安全な方法は、どこでも UTC を使用することです。

(実際、UTC に住んでいる人にはちょっと同情します。アプリからこれらのバグを取り除くことを強制されているわけではありません!)

于 2012-08-29T19:55:13.213 に答える
1

より良い方法を使用して NSDate オブジェクトを作成できます。最初に NSDate の @interface を修正します (これはどこでも実行できます)。これを行うには、これをヘッダー ファイルに入れます。

@interface NSDate (missingFunctions) 
+ (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;
@end

次に、メインファイルに次を入れます:

@implementation NSDate (missingFunctions)
+ (NSDate *)dateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day {
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setYear:year];
    [components setMonth:month];
    [components setDay:day];

    //BUT MOST IMPORTANTLY:
    [components setTimeZone:[NSTimeZone localTimeZone]];
    [components setHour:hour];
    [components setMinute:minute];
    [components setSecond:second];

    return [calendar dateFromComponents:components];
}   
@end

次に、コード呼び出しのどこからでも (たとえば):

[NSDate dateWithYear:1969 month:8 day:15];

そして、適切なタイムゾーンでリクエストに応じて NSDate を返します。公式のアップル ドキュメントでNSTimeZoneの詳細を読んで、使用するタイム ゾーンを変更することもできます。

私がこのコードを書いたことを信用することはできませんが、動作することは保証できます。

于 2012-08-29T19:47:57.650 に答える