TimeZoneInfoを使用して、夏時間中に現地時間を取得するにはどうすればよいですか?


84

私はDateTimeOffset、任意のタイムゾーンで特定の瞬間を伝えるために使用しようとしています。TimeZoneInfo夏時間の処理方法がわかりません。

var dt = DateTime.UtcNow;
Console.WriteLine(dt.ToLocalTime());

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
Console.WriteLine(utcOffset.ToOffset(tz.BaseUtcOffset));

これは印刷されます:

2010年6月2日16:37:19
2010年6月2日15:37:19-06:00

私は中部標準時で、現在夏時間になっています。私は2行目を読ませようとしています:

2010年6月2日16:37:19-05:00

BaseUtcOffset どうやらDSTに基づいて変更されません。

適切なオフセット値で適切な時間を取得するにはどうすればよいですか?


13
+ 1-TimeZoneInfo.ConvertTimeBySystemTimeZoneIdがこれだけでは機能しないことに気が狂います:)
James Manning 2010年

@ JamesManning-dt.Kind正しく設定されていると仮定して、そうします。
マットジョンソン-パイント

回答:


61

TimeZoneInfoからUtcOffsetを取得し、それをToOffset()メソッドに渡す必要があります。

var dt = DateTime.UtcNow;
Console.WriteLine(dt.ToLocalTime());

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);
Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset)));

なるほど...タイムゾーン内の特定の日付のUTCオフセットを取得する必要があります。ありがとう。
jaminto 2010年

5
これは、新しい使い捨てを作成してオフセットを抽出する代わりに、単一の.Net関数を使用してジョブを実行するKarlGjertsenの回答と比較して最善の方法ではありませんDateTimeOffset
ErikE 2017年

59

TimeZoneInfo.ConvertTimeFromUtcを使用することもできます。これにより、夏時間が可能になります。

DateTime utc = DateTime.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);

私の国のタイムゾーンが夏のEEST、冬のEETの場合はどうなりますか?それは夏時間でどのように機能しますか?
ラミZebian

1
Windowsは、夏時間の日付とともに、タイムゾーン情報を認識しています。事前定義されたタイムゾーンの1つを選択した場合は、うまくいくはずです。
Karl Gjertsen 2018

11

または、タイムゾーン識別子をハードコーディングしたくない場合は、次のようにします。

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);

2
TimeZoneInfo.Local直接使用できませんか?なぜあなたはへの呼び出しが必要FindSystemTimeZoneByIdですか?
coderDennis 2015年

4
あなたは正しいです、私たちはそれを必要としません。私たちはこのようにそれを行うことができますDateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkDateTime, TimeZoneInfo.Local);
Pabinator 2015年

1
しかし、その後、単一のタイムゾーンに固定されます。私が推測するコードをどのように使用したいかによって異なります。:-)
Karl Gjertsen 2015年

9
これはあまり安全ではありません。アプリケーションをクラウド環境にアウトソーシングしている場合、どのタイムゾーン自体がローカルであるかがわかりません。
トム

5

私は.NETとstackoverflowの両方の初心者なので、間違っている可能性がありますが、ここに行きます:

TimeZoneInfo.ConvertTimeFromUtcを使用すると、夏時間が可能になり、タイムゾーン+可能なDSTオフセットに従って正しい時間に変換されます。ただし、結果のオブジェクトのオフセット自体は標準時間のオフセットを表示し、夏時間を考慮しません。したがって、オブジェクトに対してToStringを実行する場合は、正しい時間(時間と分)になりますが、夏時間中のオフセットが間違っているため、コードの後半で間違った瞬間が発生する可能性があります。

代わりに、GetUtcOffsetを使用して特定の時間のオフセットを取得し、DateTimeOffsetオブジェクトでToOffsetを実行すると、時間/分とオフセット自体の両方が正しく変換され、ToStringを安全に実行できます。

string ExpectedDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss''zzz";
string timeZoneId = "FLE Standard Time";
string dateTimestr = "2017-10-09T09:00:00+02:00";

DateTimeOffset dto = DateTimeOffset.Parse(dateTimeStr);
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
TimeSpan offset = zone.GetUtcOffset(dto);
dto = dto.ToOffset(offset);
string localTime = dto.ToString(ExpectedDateTimePattern);

localTimeは「2017-10-09T10:00:00 + 03:00」を返します。


OPによると、これは正解です。理解すべき主なことは、timzoneのUtcOffsetは一定ではなく、夏時間のルールのために、日付自体に依存しているということです。したがって、OPが行った唯一の間違いは、GetUtcOffset(myDate)の代わりに定数BaseUtcOffsetを使用したことです
g.pickardou
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.