web-dev-qa-db-ja.com

NSDateFormatterを使用してUTCを現地時間に変換します

IOSアプリのサーバーから次の文字列を取得しています。

20140621-061250

どうすれば現地時間に変換できますか?

日付フォーマッターを定義するにはどうすればよいですか?これは正しいです?

dateFormatter.dateFormat = @"YYYYMMd-HHmmss"; 
9
cateof

この質問では、変換の意味を正確に指定していませんが、最終的な目標に関係なく、最初に行う必要があるのは、適切に構成されたNSDateFormatterを使用してサーバー応答を正しく解析することです。これには正しいフォーマット文字列の指定が必要であり、タイムゾーンはフォーマッタで明示的に設定する必要があります。そうしないと、現地時間から推測されますが、ほとんどの場合正しくありません。

フォーマット文字列を指定します

提供された入力文字列を見てみましょう。

20140621-061250

これは、年に4桁、月に2桁(ゼロパディングあり)、日に2桁(おそらくこれらもゼロパディングされる)を使用します。この後に-が続き、次に時間を表す2桁、分を表す2桁、秒を表す2桁が続きます。

nicode日付形式標準 を参照すると、次の方法で形式文字列を導出できます。暦年を表す4桁は、フォーマット文字列のyyyyに置き換えられます。月にはMMを使用し、日にはddを使用します。次はリテラル-です。時間については、24時間形式になると想定しています。そうでない場合、この応答はあいまいになるため、HHを使用します。その場合、分はmmで、秒はssです。フォーマット指定子を連結すると、次のフォーマット文字列が生成されます。これは次のステップで使用します。

yyyyMMdd-HHmmss

私たちのプログラムでは、これは次のようになります。

NSString *dateFormat = @"yyyyMMdd-HHmmss";

入力日付フォーマッターを構成します

上記の時間形式はタイムゾーンを指定していませんが、UTC時間を表すサーバー応答の仕様が提供されているため、これをアプリケーションにコーディングできます。したがって、NSDateFormatterをインスタンス化し、正しいタイムゾーンを設定し、日付形式を設定します。

NSTimeZone *inputTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init];
[inputDateFormatter setTimeZone:inputTimeZone];
[inputDateFormatter setDateFormat:dateFormat];

入力文字列をNSDateに変換します

デモンストレーションの目的で、サーバーの応答から受け取った文字列をハードコーディングします。このinputStringの定義を、サーバーから取得した定義に置き換えます。

NSString *inputString = @"20140621-061250";
NSDate *date = [inputDateFormatter dateFromString:inputString];

この時点で、さらに変換または計算を行うために必要なオブジェクトがあります。これは、サーバーから通信された時間を表すNSDateです。 NSDateは単なるタイムスタンプであり、タイムゾーンとはまったく関係がなく、日付の文字列表現、またはNSDateComponentsを介した暦日の表現との間で変換する場合にのみ役割を果たします。

次のステップ

この質問では、必要な変換の種類が明確に指定されていないため、サーバーの応答と同じ形式で表示するように日付をフォーマットする例を示します(ただし、これの使用例は考えられません。正直なところ、特定のコード)。手順は非常に似ています。フォーマット文字列とタイムゾーンを指定し、日付フォーマッタを設定してから、日付から文字列(指定された形式)を生成します。

NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone];
NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
[outputDateFormatter setTimeZone:outputTimeZone];
[outputDateFormatter setDateFormat:dateFormat];
NSString *outputString = [outputDateFormatter stringFromDate:date];

私はUTC-06:00にいるので、outputStringを印刷すると次のようになります。

20140621-001250

この日付をユーザーに表示する場合は、フォーマット文字列の代わりにsetDateStyle:setTimeStyle:を使用するか、NSCalendarを使用してNSDateComponentsインスタンスを取得して算術計算または計算を行うことをお勧めします。日付に。詳細な日付文字列をユーザーに表示する例:

NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone];
NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
[outputDateFormatter setTimeZone:outputTimeZone];
[outputDateFormatter setDateStyle:NSDateFormatterFullStyle];
[outputDateFormatter setTimeStyle:NSDateFormatterFullStyle];
NSString *outputString = [outputDateFormatter stringFromDate:date];

ここにoutputStringを印刷すると、次のようになります。

2014年6月21日土曜日午前12:12:50山岳部夏時間

タイムゾーンを適切に設定すると、夏時間の移行が処理されることに注意してください。上記のフォーマッタスタイルコードを使用して入力文字列を「20141121-061250」に変更すると、次の日付が表示されます(山岳部標準時はUTC-7であることに注意してください)。

2014年11月20日木曜日11:12:50 PM山岳部標準時

概要

カレンダーの日付と時刻を表す文字列形式で日付入力を取得するときはいつでも、最初のステップは、入力のソースに応じて、入力の形式、タイムゾーン、場合によってはロケールとカレンダー用に構成されたNSDateFormatterを使用して日付を変換することです。あなたの要件。これにより、ある瞬間の明確な表現であるNSDateが生成されます。そのNSDateの作成に続いて、アプリケーションの要件に応じて、フォーマット、スタイル設定、または日付コンポーネントへの変換を行うことができます。

36
Carl Veazey

文字列をNSDateに取り込むには、次のように NSDateFormatter を使用します。

NSString *myDateAsAStringValue = @"20140621-061250"
NSDateFormatter *df = [[NSDateFormatter alloc] init];    
[df setDateFormat:@"yyyyMMdd-HHmmss"];
NSDate *myDate = [df dateFromString: myDateAsAStringValue];

日付と時刻の操作 に関するこの投稿を読むことをお勧めします

編集:

UTCとして解析するには、次の行を追加する必要があります。

[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];

また、NSLogを使用して印刷する場合、同じNSDateFormatterを使用していると、入力文字列が出力として取得されます(解析関数の逆関数を適用するため)。

解析および標準形式で出力を取得するための完全なコードは次のとおりです。

//The input
NSString *myDateAsAStringValue = @"20140621-061250";

//create the formatter for parsing
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
[df setDateFormat:@"yyyyMMdd-HHmmss"];

//parsing the string and converting it to NSDate
NSDate *myDate = [df dateFromString: myDateAsAStringValue];

//create the formatter for the output
NSDateFormatter *out_df = [[NSDateFormatter alloc] init];
[out_df setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssz"];

//output the date
NSLog(@"the date is %@",[out_df stringFromDate:myDate]);
9
Daniel

Swift NSDate拡張機能を使用した1つの可能な解決策(おそらく、この質問の将来の視聴者に役立つ可能性があります):

import UIKit

// For your personal information: NSDate() initializer 
// always returns a date in UTC, no matter the time zone specified.
extension NSDate {
    // Convert UTC (or GMT) to local time
    func toLocalTime() -> NSDate {
        let timezone: NSTimeZone = NSTimeZone.localTimeZone()
        let seconds: NSTimeInterval = NSTimeInterval(timezone.secondsFromGMTForDate(self))
        return NSDate(timeInterval: seconds, sinceDate: self)
    }

    // Convert local time to UTC (or GMT)
    func toGlobalTime() -> NSDate {
        let timezone: NSTimeZone = NSTimeZone.localTimeZone()
        let seconds: NSTimeInterval = -NSTimeInterval(timezone.secondsFromGMTForDate(self))
        return NSDate(timeInterval: seconds, sinceDate: self)
    }
}
8
King-Wizard