web-dev-qa-db-ja.com

UTC / GMT時間を現地時間に変換します。

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のある種の設定ですか?

281
nzpcmad

2012-09-19 01:27:30.000のような文字列の場合、DateTime.Parseは日付と時刻がどのタイムゾーンのものであるかを知ることができません。

DateTimeにはKindプロパティがあり、3つのタイムゾーンオプションのうちの1つを持つことができます。

  • 指定なし
  • 地元
  • UTC

NOTEUTCまたはあなたの地域のタイムゾーン以外の日付/時刻を表したい場合は、 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();

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

361
Drew Noakes

あなたが.NET 3.5にいるならば、私はSystem.TimeZoneInfoクラスを使うことになるでしょう。 http://msdn.Microsoft.com/ja-jp/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);
114
TimeZone.CurrentTimeZone.ToLocalTime(date);
48
coder1

DateTimeオブジェクトはデフォルトでKindUnspecifiedを持ちます。これはToLocalTimeの目的のためにUTCと見なされます。

UnspecifiedDateTimeオブジェクトの現地時間を取得するには、こうするだけです:

convertedDate.ToLocalTime();

KindDateTimeUnspecifiedからUTCに変更するステップは不要です。 Unspecifiedは、UTCの目的でToLocalTimeと見なされます。 http://msdn.Microsoft.com/ja-jp/library/system.datetime.tolocaltime.aspx

21
CJ7

私はこれがより古い質問であることを知っています、しかし、私は同様の状況に遭遇しました、そして私は私自身を含むこともあるかもしれません。

DateTime.Parse()は扱いにくいかもしれません - 例えばここで を見てください

DateTimeがWebサービスまたはその他の既知の形式のソースから来ている場合は、次のようなものを検討します。

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

あるいは、もっと良い

DateTime.TryParseExact(...)

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

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

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

アプリをプロファイリングしたところ、DateTime.ParseがCPU使用率のかなりの割合を占めていることがわかりました。 (ちなみに、CultureInfoコンストラクタはCPU使用率への重要な貢献者ではありませんでした。)

そこで、私はさまざまな方法で日付/時刻文字列を10000回解析するようにコンソールアプリを設定しました。一番下の行
Parse() 10秒
ParseExact()(ローカルに変換)20-45ミリ秒
ParseExact()(ローカルには変換されません)10-15 ms
...そしてそうです、Parse()の結果はですが、他の結果はミリ秒です。

16
David

一般的な注意を追加したいだけです。

あなたがしているのがディスプレイまたはレポートに日付/時刻を置くためにコンピュータの内部時計から現在の時刻を得ることだけであれば、それですべてうまくいきます。しかしあなたが 節約 後で参照するための日時情報 コンピューティング 日付/時間、用心しなさい!

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

14
Mark T

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

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

余分な時間をどのように調整しますか?

指定しない限り、.netはローカルのPC設定を使用します。 http://msdn.Microsoft.com/ja-jp/library/system.globalization.daylighttime.aspx

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

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

そして上で述べたように、あなたのサーバーがどのタイムゾーン設定になっているかを二重にチェックしてください。安全にIISの変更に影響を与える方法についてのネット上の記事があります。

4
Brendan Kowitz
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
3
Prince Prasad

Danaの提案に答えて

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

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

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

"conversionDate"と "dt"は同じです。

21/08/08 10:00:26;地元の人

2
nzpcmad

あなたがTwitter APIを介して返されるUTCの日付(ステータスのcreated_atフィールド)に問題があったので、私はこの質問に出会いました。それらをDateTimeに変換する必要があります。このページの回答の中の回答/コードサンプルのどれも、「文字列は有効なDateTimeとして認識されませんでした」というエラーが表示されるのを防ぐのに十分ではありませんでした。

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

1
DannykPowell

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

変更したくない場合は、Unspecifiedに設定します。

1
Miles