web-dev-qa-db-ja.com

Objective-C、UTCタイムゾーンで現在の日付を取得するにはどうすればよいですか?

やっています:

NSDate *currentDateInLocal = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSString *currentLocalDateAsStr = [dateFormatter stringFromDate:currentDateInLocal];

NSDateFormatter * dateFormatter2 = [[NSDateFormatter alloc] init];
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
[dateFormatter2 setTimeZone:timeZone];
[dateFormatter2 setDateFormat:@"yyyy-MM-dd'T'HH:mm:SS.SSS'Z'"];
NSDate *currentDateInUTC = [dateFormatter2 dateFromString:currentLocalDateAsStr];

しかし、それはまだ現在のUTC時間を表していないのですが、どうすればこれを達成できますか?

ありがとう

37
Baconbeastnz

あなたは物事を複雑にしています。

NSDatesにはタイムゾーンまたはカレンダーがありません。 [NSDate date]は現在の日付を取得します。これは、履歴内の瞬間の測定値です。ヨーロッパで[NSDate date]をアメリカで実行するのとまったく同時に実行すると、まったく同じ値が得られます。

日付の印刷方法は、カレンダーとタイムゾーンによって異なります。したがって、グレゴリオ暦で印刷された日付は、ユリウス暦で印刷された日付とは異なって見えます。また、UTCグレゴリオ暦で印刷された日付は、PSTグレゴリオ暦で印刷された日付とは異なって見えます。しかし、彼らはまだ同じ日付です。

したがって、dateFormatter2に直接ジャンプする必要があります。

51
Tommy

受け入れられた Alex Wienによる回答incorrectです。

デフォルトでは、NSDateFormatterはNSDateの日時値をUTCからユーザーのローカルタイムゾーンに調整します。この調整を防ぐには、NSDateFormatterにUTCのタイムゾーンを使用するように指示します。

結果を確認するには、「現在時刻utc」をGoogleで検索します。

以下の私のソースコードは仕事をする必要があります。つまり、現在の日時を [〜#〜] utc [〜#〜]ISO 8601形式 の文字列として取得します。 ( Zul )最後にZで示されるタイムゾーン。

NSDate* datetime = [NSDate date];
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; // Prevent adjustment to user's local time zone.
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];

このロジックは、アプリのどこかにある便利なメソッドのペアに入れることができます。

- (NSString*)now
{
    // Purpose: Return a string of the current date-time in UTC (Zulu) time zone in ISO 8601 format.
    return [self toStringFromDateTime:[NSDate date]];
}

…そして…

- (NSString*)toStringFromDateTime:(NSDate*)datetime
{
    // Purpose: Return a string of the specified date-time in UTC (Zulu) time zone in ISO 8601 format.
    // Example: 2013-10-25T06:59:43.431Z
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"];
    NSString* dateTimeInIsoFormatForZuluTimeZone = [dateFormatter stringFromDate:datetime];
    return dateTimeInIsoFormatForZuluTimeZone;
}

使用例…

NSString* now = [self now];

または、これらのマイナス記号をプラス記号に変換して、インスタンスメソッドではなくクラスメソッドとして使用します…

NSString* now = [SomeClassNameHere now];

ヒント:人間が読みやすくするために、フォーマットのTをスペースに変更してください。ソフトウェアによる相互運用性を向上させるには、Tを維持します。 ISO 8601仕様はスペースを許容しますが、Tを保持することをお勧めします。


ヒント:テストしていませんが、…インスタンス化[NSDateFormatter][4] 高いです。頻繁に行う場合(ループ内など)、再利用のために単一のインスタンスをキャッシュすることを検討してください。

39
Basil Bourque

カレンダー識別子を設定してください!!!

私は手遅れではありません!誰もCalendar Identifierを設定していないのを見たからです。 本当に重要世界中のユーザーにとって。非グレゴリオ暦を使用する多くのユーザー。彼らは間違った年の文字列を取得します。特に、独自のデータベースに保存する必要がある場合。 (以前にこの問題に遭遇しました)

NSCalendarIdentifierGregorian
NSCalendarIdentifierBuddhist
NSCalendarIdentifierChinese
NSCalendarIdentifierHebrew
NSCalendarIdentifierIslamic
NSCalendarIdentifierIslamicCivil
NSCalendarIdentifierJapanese
NSCalendarIdentifierRepublicOfChina
NSCalendarIdentifierPersian
NSCalendarIdentifierIndian
NSCalendarIdentifierISO8601

コード:

-(NSString *)getUTCFormateDate:(NSDate *)localDate
{
    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
    [dateFormatter setCalendar:gregorianCalendar];
    [dateFormatter setTimeZone:timeZone];
    [dateFormatter setLocale:locale];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString *dateString = [dateFormatter stringFromDate:localDate];
    return dateString;
}  
10
Yi Jiang

[NSDate date]はUTCです。たぶん、あなたは地元の人を見ることでだまされますか?次に、タイムゾーンに変換されます。

ローカルで値が表示される場合、ローカル時間で表示されますが、コンソールで値を印刷する場合、UTCで表示されます。

時間の後に「+0000」が表示されたら、UTCであることがわかります

2
Cub71

Swift

let utcTimestamp = Date().timeIntervalSince1970
print("timeStamp = \(utcTimestamp)")

5月以降の拡張が簡単になります。

Swift 4:UTC/GMT⟺ローカル(現在/システム)

extension Date {

    // Convert local time to UTC (or GMT)
    func toGlobalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }

    // Convert UTC (or GMT) to local time
    func toLocalTime() -> Date {
        let timezone = TimeZone.current
        let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
        return Date(timeInterval: seconds, since: self)
    }

}


// Try it
let utcDate = Date().toGlobalTime()
let localDate = utcDate.toLocalTime()

print("utcDate - (utcDate)")
print("localDate - (localDate)")
1
Krunal

これは私が使用したものです。

_static func makeISO8601Date(isoDateString: String) -> Date {
    let formatter = DateFormatter()
    formatter.calendar = Calendar(identifier: .iso8601)
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"

    return formatter.date(from: isoDateString)
}
_

makeISO8601Date(isoDateString: "2017-12-31T23:59:59+00:00")

0
amol-c

それを行う別の方法は、Objective CプロジェクトのC++クラスの場合です。 (したがって、.mmファイルを作成し、パブリックパーツとプライベートパーツを使用してC++クラスを構築し、パブリックパーツに貼り付けます(プライベートにする必要がない場合)。次に、NSString *sNowUTC = MyClass::getUTCTimestamp();のように参照します。

static NSString *getUTCTimestamp(){
  time_t rawtime;
  struct tm * timeinfo;
  char buffer [80];
  time (&rawtime);
  timeinfo = gmtime (&rawtime);
  // make format like "2016-06-16 02:37:00" for 
  //   June 16, 2016 @ 02:37:00 UTC time
  strftime (buffer,80,"%F %T",timeinfo);
  std::string sTime(buffer);
  NSString *sUTC = @(sTime.c_str());
  return sUTC;
}
0
Volomike