多くのWebサイト(通常はフォーラム)では、ユーザーが次を選択してTimeZone設定を指定できることを確認しました。
- TimeZone
- DSTを使用するかどうか
私の知る限り、変換を行うとき、.NETは常にDSTを考慮に入れるため、問題は次のとおりです。
「DSTを使用しない」部分をC#で実装するにはどうすればよいですか?
このポイントの下で、私はこれまでに何とかしたことを提示しますが、それはハッキーな感じがして、よりクリーンでより良いアプローチがあるかどうか疑問に思いました。
まず、DSTが自動的に適用されることを確認するために、次のテストを作成しました。
[Test]
public void DateTimeConversion_ToLocalTime_HandlesDSTByDefault()
{
var utcDateInDstInterval = new DateTime(2012, 07, 15, 0, 0, 0, DateTimeKind.Utc);
var utcDateOutisdeDstInterval = new DateTime(2012, 02, 15, 0, 0, 0, DateTimeKind.Utc);
var roTimezone = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time");
Assert.AreEqual(3, TimeZoneInfo.ConvertTimeFromUtc(utcDateInDstInterval, roTimezone).Hour);
Assert.AreEqual(2, TimeZoneInfo.ConvertTimeFromUtc(utcDateOutisdeDstInterval, roTimezone).Hour);
}
このテストは合格し、次のことを示しています。
- DSTが適用されない場合(たとえば冬季)、ルーマニアの時刻はUTC+2時間です。
- DSTが適用される場合(たとえば夏時間)、ルーマニアの時刻はUTC+3時間です。
- 日時変換を行う場合、DSTは自動的に考慮されます
TimeZoneInfo.GetAdjustmentRules()
次に、オブジェクトの配列を返すメソッドに気づき、AdjustmentRule
これらのルールの効果を元に戻すと、DSTの影響を受けない値を取得できることがわかりました。
DateTime
そのため、オブジェクトがDSTの影響を受ける場合に、これを行う次のメソッドを作成しました。
private DateTime RemoveDSTFromDateTime(DateTime dateTime, TimeZoneInfo timeZoneInfo)
{
if (!dateTime.IsDaylightSavingTime())
return dateTime;
var result = dateTime;
foreach (var adjustmentRule in timeZoneInfo.GetAdjustmentRules())
result = result.Subtract(adjustmentRule.DaylightDelta);
return result;
}
元のDST/DSTなしのシナリオに戻りますが、今回は結果がDSTの影響を受けないようにします。
[Test]
public void DateTimeConversion_ToLocalTime_WithoutDST()
{
var utcDateInDstInterval = new DateTime(2012, 07, 15, 0, 0, 0, DateTimeKind.Utc);
var utcDateOutisdeDstInterval = new DateTime(2012, 02, 15, 0, 0, 0, DateTimeKind.Utc);
var roTimezone = TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time");
var convertedDateWithDst = TimeZoneInfo.ConvertTimeFromUtc(utcDateInDstInterval, roTimezone);
var convertedDateWithoutDst = TimeZoneInfo.ConvertTimeFromUtc(utcDateOutisdeDstInterval, roTimezone);
Assert.AreEqual(2, RemoveDSTFromDateTime(convertedDateWithDst, roTimezone).Hour);
Assert.AreEqual(2, RemoveDSTFromDateTime(convertedDateWithoutDst, roTimezone).Hour);
}
このテストも合格し、DSTの影響がキャンセルされたことを示しています(時期に関係なく、常にUTC + 2hを取得します)。
これを書き留めていると、うまくいくように見える別のアイデアが浮かびました。メソッドを使用する代わりに、UTC日付にTimeZoneInfo.Convert...()
追加するだけです。roTimezone.BaseUtcOffset
誰かがこれを行う正しい方法を示すことができますか?