UTC / GMT時間を現地時間に変換する


301

Webサービスクライアント用のC#アプリケーションを開発しています。これはWindows XP PCで動作します。

Webサービスによって返されるフィールドの1つは、DateTimeフィールドです。サーバーはGMT形式でフィールドを返します。つまり、末尾に「Z」が付いています。

ただし、.NETはなんらかの暗黙の変換を行うようであり、時間は常に12時間でした。

次のコードサンプルは、12時間の差がなくなったという点でこれをある程度解決していますが、ニュージーランドの夏時間を考慮していません。

CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            

あたりとしてこの日付サイト

UTC / GMTオフセット

標準時間帯:UTC / GMT +12時間
夏時間:+1時間
現在の時間帯オフセット:UTC / GMT +13時間

延長時間をどのように調整しますか?これはプログラムで実行できますか、それともPCの設定のようなものですか?


2
Z時間はUTCではなくGMTを指します。2つは、最大0.9秒異なる場合があります。
mc0e 2017

回答:


374

以下のような文字列の場合は2012-09-19 01:27:30.000DateTime.Parse日付と時刻から何であるかを時間帯伝えることはできません。

DateTime持っている種類の 3つの時間帯のいずれかのオプションを持つことができるプロパティを、:

  • 不特定
  • 地元
  • UTC

UTCまたはローカルタイムゾーン以外の日付/時刻を表現する場合は、を使用する必要がありますDateTimeOffset


だからあなたの質問のコードについて:

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

あなたはそれがどんな種類か知っていると言うので、それを教えてください。

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

これで、システムがUTC時間でそれを知ると、次のように呼び出すことができますToLocalTime

DateTime dt = convertedDate.ToLocalTime();

これにより、必要な結果が得られます。


19
種類を指定するもう1つの方法:DateTime convertedTime = new DateTime(DateTime.Parse(dateStr).Ticks), DateTimeKind.Utc);
Brad

ToLocalTime()ではないですか?@Brad-括弧が一致しません。
TrueWill、2011

2
このソリューションは夏時間を考慮していますか?やってみると、1時間オフです。
ボブ・ホーン

7
変更のステップKindのをDateTimeからUnspecifiedにはUTC不要です。Unspecifiedであると仮定されるUTCの目的のためにToLocalTimemsdn.microsoft.com/en-us/library/...
CJ7

16
@ CJ7:はい。ただし、明示的にすることは、コードを保守する必要がある他の開発者にとって特に役立ちます。
Ryan

121

.NET 3.5を使用している場合は、System.TimeZoneInfoクラスの使用を検討します。http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspxを参照してください。これにより、夏時間の変更が正しく考慮されます。

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u");
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone.
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime();

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone"
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx
string nzTimeZoneKey = "New Zealand Standard Time";
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey);
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone);

自分のタイムゾーン(この場合はen-NZ)で作業している場合は、TimeZoneInfoを処理する必要はありません。それは単に不必要な複雑さです。詳細については、私の回答を参照してください。
Drew Noakes、

11
そして、必要な場合は、TimeZoneInfo.FindSystemTimeZoneById-codeproject.com/ Messages
3867850

鮮やかさ!この投稿をありがとう、ダン。私はこの修正を3日間探していました。
ケビンムーア

58
TimeZone.CurrentTimeZone.ToLocalTime(date);

8
これは、変換元の日付がUTCであることをシステムが認識している場合にのみ機能します。私の答えを見てください。
Drew Noakes、

1
しかし、UTCがデフォルトですよね。したがって、CJ7の回答のように「未指定」で機能します。
NickG 2013年

25

DateTimeオブジェクトが持っているKindのをUnspecifiedする目的のために、デフォルトでToLocalTimeあると想定されますUTC

Unspecified DateTimeしたがって、オブジェクトのローカル時間を取得するには、次のようにする必要があります。

convertedDate.ToLocalTime();

変更のステップKindのをDateTimeからUnspecifiedにはUTC不要です。UnspecifiedUTCの目的であると想定されていますToLocalTimehttp : //msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx


6
逆も同様です:convertedDate.FromLocalTime();に変換されUTCます。
R. Schreurs 2017

16

これは古い質問であることはわかっていますが、同じような状況に遭遇し、将来の検索者のために見つけたものを共有したいと思いました。

DateTime.Parse()トリッキーになる可能性があります- たとえば、ここを参照してください。

DateTime既知の形式のWebサービスまたはその他のソースからのものである場合、次のようなものを検討することができます。

DateTime.ParseExact(dateString, 
                   "MM/dd/yyyy HH:mm:ss", 
                   CultureInfo.InvariantCulture, 
                   DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)

または、さらに良いことに、

DateTime.TryParseExact(...)

AssumeUniversalフラグは、日付/時刻がすでにUTCであることをパーサに指示します。組み合わせAssumeUniversalとは、AdjustToUniversalそれがデフォルトで行うようにしようと「ローカル」の時間に結果を変換しないことを伝えます。(私は個人的にはとにかくビジネス/アプリケーション/サービスレイヤーでUTCのみに対処しようとします。しかし、現地時間への変換をバイパスすることによってもスピードアップします-私のテストでは50%以上、以下を参照してください。)

これが私たちが以前やっていたことです:

DateTime.Parse(dateString, new CultureInfo("en-US"))

アプリのプロファイルを作成したところ、DateTime.ParseがCPU使用率のかなりの割合を占めていることがわかりました。(ちなみに、CultureInfoコンストラクターはCPU使用率の大きな原因ではありませんでした。)

そこで、さまざまな方法で日付/時刻文字列を10000回解析するようにコンソールアプリを設定しました。ボトムライン:
Parse()10秒
ParseExact()(ローカルへの変換)20-45ミリ秒
ParseExact()(ローカルに変換しない)10〜15ミリ秒
...はい、の結果がParse()でている他の人がしているのに対し、ミリ秒


14

一般的な注意事項を追加します。

コンピュータの内部時計から現在の時刻を取得して、日付または時刻をディスプレイまたはレポートに表示するだけの場合は、問題はありません。ただし、後で参照できるように日付/時刻情報を保存する場合、または日付/時刻を計算する場合は、注意してください。

2007年12月20日15:00 UTCにクルーズ船がホノルルに到着したと判断したとします。そして、あなたはそれが何時であったか知りたいのです。
1.おそらく少なくとも3人の「地元住民」が関わっています。ローカルとは、ホノルルを意味する場合と、コンピュータが配置されている場所を意味する場合と、顧客が配置されている場所を意味する場合があります。
2.組み込み関数を使用して変換を行う場合、おそらく間違っているでしょう。これは、サマータイムが(おそらく)現在コンピュータで有効になっているが、12月には無効だったためです。しかし、Windowsはこれを認識していません...夏時間が現在有効であるかどうかを判断するためのフラグが1つだけあります。そして、それが現在有効であれば、12月の日付でさえも1時間は喜んで追加されます。
3。夏時間は、さまざまな政治的区分で異なって(またはまったく)実装されていません。あなたの国が特定の日に変化するからといって、他の国も変化するとは考えないでください。


6
実際、#2は完全に正しいわけではありません。実際には、情報がインストール(および更新)されているかどうかをコンピューターが認識するすべてのタイムゾーンのDSTに関するルールがあります。多くのゾーンでは、これらのルールは固定されています。他は「動的DST」を実装します。ブラジルはこれに対する私のうんざりです。要約すると、あなたのローカル時間が12月の夏時間であるなら、あなたのヘリコプターはうまくいくことができます。
ロジャーウィルコックス

ブラジルに住んでいない場合でも、政治家はいつでも変更できるという点でDSTは「ダイナミック」です(数年前に米国で行われたように)。ほとんどのソフトウェアは将来の使用を念頭に置いて作成されているため、どのDSTルールが有効になるかを知るための実用的で予測可能な、または理論的な方法さえないことを認識することが重要です。あなたは近づくことができますが、完璧をあきらめることによって自分自身にいくつかの不満を救います。
DaveWalley、2014年


5

既にDateTimeオブジェクトがあり、それがUTCであるかLocalであるかがわからない場合は、オブジェクトのメソッドを直接使用するのが簡単なので、忘れないでください。

DateTime convertedDate = DateTime.Parse(date);
DateTime localDate = convertedDate.ToLocalTime();

延長時間をどのように調整しますか?

特に指定しない限り、.netはローカルのPC設定を使用します。私は以下を読みます:http : //msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

見た目では、コードは次のようになります。

DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year );

上記のように、サーバーのタイムゾーン設定を再確認してください。IISの変更に安全に影響を与える方法については、ネット上の記事があります。


システムがこの複雑さを処理するのは、日付が「種類」(local / utc / unspecified)であるとシステムに伝えた場合です。
Drew Noakes、

2

ダナの提案に答えて:

コードサンプルは次のようになります。

string date = "Web service date"..ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate);

元の日付は20/08/08でした。種類はUTCでした。

「convertedDate」と「dt」はどちらも同じです。

21/08/08 10:00:26; 種類はローカルでした


これの説明については私の答えを見てください。
Drew Noakes、

1

DataColumnのDateTypeフィールドがローカルに設定されているため、ネットワーク(Webサービスからクライアント)を介してプッシュされるデータセット内にあるため、自動的に変更されるという問題がありました。DataSetをプッシュする場合は、DateTypeを確認してください。

変更したくない場合は、「未指定」に設定します


1

この質問に出くわしたのは、Twitter API(ステータスのcreated_atフィールド)から返されるUTC日付に問題があったためです。それらをDateTimeに変換する必要があります。このページの回答の回答/コードサンプルのいずれも、「文字列が有効なDateTimeとして認識されませんでした」というエラーを表示するのに十分ではありませんでした(ただし、SOで正しい回答を見つけるのに最も近いものです)

これが他の人を助ける場合に備えて、このリンクをここに投稿します-私が必要とした答えは、このブログ投稿で見つかりました:http : //www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ -基本的に、DateTime.Parseの代わりにフォーマット文字列を含むDateTime.ParseExactを使用します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.