2012-06-30 13 views
9

NSDateFormatter私のアプリケーションで日付文字列を受け取り、NSDateにフォーマットするようにしていますが、dateFromStringを使用して日付をフォーマットすると、日付比較ができますある日失う。NSDateFormatter dateFromStringが不正な日付を返す

NSString *dateString = @"02-06-2012"; 
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
[dateFormatter setDateFormat:@"dd-MM-yyyy"]; 
NSDate *dateFromString = [[NSDate alloc] init]; 
dateFromString = [dateFormatter dateFromString:dateString]; 
NSLog(@"My Date = %@", dateFromString); 
[dateFormatter release]; 

これは、コンソールに出力します。あなたのコードにこの行を追加する

私の日= 2012年6月1日23時○○分00秒0000

答えて

19

Iドルフの答えが正しいとは思わないでください。実際には、何か問題があることは明らかではありません。あなたは何が起こるべきか、起こっていることの解釈を誤っているようです。

NSDateは、ある瞬間を表します。この瞬間には一意の名前はありません。異なる場所や異なる命名システム(タイムゾーン、カレンダー)で異なる名前で知られています。 NSDateは、-descriptionメソッドで嘆かわしいことを除いて、これを処理しません。そのメソッドは、その瞬間の文字列表現を生成する必要があります。

第2に、「02-06-2012」のような文字列は正確な瞬間を指定しません。まず、時刻情報のない日付だけなので、NSDateFormatterはその日付の最初の瞬間になります。次に、タイムゾーンを指定しません。暦日の最初の瞬間は、各時間帯の異なる瞬間です。 -setTimeZone:でタイムゾーンを指定しないか、または文字列自体にタイムゾーン情報が含まれていない限り、NSDateFormatterは、解析するよう要求された日付文字列が現在のタイムゾーンにあるとみなします。

したがって、dateFromStringオブジェクトは、指定した日付の最初の瞬間(02-06-2012)をあなたのタイムゾーンで表します。これがあなたの望むものだと思います。しかし、ログしたときにNSDateが自分自身を記述する方法で混乱してしまいました。私が言ったように、NSDateは、それが表す瞬間のためにいくつかの "名前"(文字列表現)を選択しなければならず、どの名前を選ぶかはかなり恣意的です。最近では、その瞬間がUTCで知られている名前を選んでいます。私はUTC + 0100に位置していることをあなたの質問に示されたログ出力から収集します。だから、日付は1日前のように見えるかもしれませんが、実際に指定したのと同じです。つまり、「2012-06-01 23:00:00 +0000」と「2012-06-02 00:00:00 +0100」は、まったく同じ瞬間の2つの同等の名前です。あなたはちょうど最初のものを見るのに慣れておらず、それを誤解しました。

NSDateの自己記述を特定の時間帯にすることをやめる必要があるということが教訓です。本当に、文書化されていないので、あなたはそれについて何も信頼してはいけません。実際、-[NSDate description]のドキュメントでは、「表現がオペレーティングシステムの異なるリリース間で一定に保たれることは保証されていません」と述べています。

ドルフの解は、NSDateFormatter-[NSDate description]がタイムゾーンで一致するため、と思われます。しかし、それは信頼できません。たとえば、-[NSDate description]は、そのバージョンのフレームワークでUTCではなくローカルタイムゾーンを使用していたため、Snow Leopardでは動作しません。

もっと重要なのは、NSDateFormatterの日付文字列の解釈から得られるNSDateオブジェクトによって表される実際の瞬間を変更することです。私はあなたが本当にそれが特定の意味を持つことを望んでいると思っています - 文字列を現地のタイムゾーンにあるものとして解釈したいと思っていて、彼の解決策があなたの意図を妨害しています。

tl; dr:あなたはいつもあなたが望んでいた日付を取得していました。 -[NSDate description]に頼らないでください。 Dhruvのソリューションを使用しないでください

+0

こんにちはケン、詳細な返信をありがとう、私は何をやりたいの?私のアプリでは、チェックする必要があると等しいか、私は私のアプリに入れておく必要がある特定のハードコードされた日付よりも大きいです。おかげで – MonkeyBlue

+1

あなたは本当にあなたが何の瞬間を決定する必要があります。ハードコードされた日付は、特定の固定時間帯(会​​社の自宅のようなもの)にあると解釈されることを意味していますか?それとも、それはユーザーのタイムゾーンにあると解釈されるはずですか?前者の場合は、日付フォーマッタで固定のタイムゾーンを設定する必要があります。後者の場合は、デフォルトのままにしておくか、明示的に '[NSTimeZone defaultTimeZone]'(または '+ systemTimeZone')に設定することができます。 –

+0

ありがとうKen私はそれを行ってくれます - 固定時間は基本的に特定の日付ですので、あなたがどこにいてもアプリケーションを開くならば、それは特定の日付を使用し、今日がより大きいか等しいかを見なければなりません。特定の日付から別の情報をアプリに表示する必要があるためです。あなたの説明もまた意味があるので、私はあなたの答えをマークアップします。ありがとう – MonkeyBlue

49

てみてください、

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT+0:00"]]; 

または

[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; 

SWIFT更新:quetionから

コード、

let dateString = "02-06-2012" 
var dateFormatter = NSDateFormatter() 
dateFormatter.dateFormat = "dd-MM-yyyy" 
var dateFromString : NSDate = dateFormatter.dateFromString(dateString)! 
println("My Date \(dateFromString)") 

、その溶液、

dateFormatter.timeZone = NSTimeZone(name: "GMT") 

OR

dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+0:00") 
+0

ありがとう、それは完璧です。 – MonkeyBlue

+0

これは非汎用ソリューションではありませんか?デバイスがGMT上にない場合はどうなりますか? – Stavash

+4

@stavashそれがポイントです、GMTはUTC、つまり世界時と同じです。誰もが使用できる標準化された1つのタイムゾーンで、夏時間のために変更されることはありません。これは、iOSが日付/時刻を保存する方法です。 – lnafziger

関連する問題