Cri*_*scu 5 c# datetime dst c#-4.0
我已经看到许多网站(通常是论坛)允许用户通过选择以下内容来指定他们的TimeZone首选项:
据我所知,在进行转换时,.NET总是将DST考虑在内,所以问题是:
在这一点下面,我介绍了我到目前为止所做的工作,但感觉很烦,而且我想知道是否有更清洁/更好的方法.
首先,为了确保自动应用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);
}
Run Code Online (Sandbox Code Playgroud)
该测试通过,表明:
接下来,我注意到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;
}
Run Code Online (Sandbox Code Playgroud)
返回到原始DST/No 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);
}
Run Code Online (Sandbox Code Playgroud)
此测试也通过,表明现在DST的效果被取消(无论一年中的哪个时间,我们总是得到UTC + 2h).
写下来时,我得到了另一个似乎有用的想法:不使用任何TimeZoneInfo.Convert...()方法,只需添加roTimezone.BaseUtcOffset到UTC日期即可.
任何人都可以指出这样做的正确方法是什么?
解析您的问题,您似乎有两个建议的解决方案:
确定 DST 调整并将其从转换后的输出中删除。
采用 UTCDateTime并添加 ,BaseUtcOffset以便您始终处理标准时间。
由于您的问题是如何不实施 DST,我想说您自己用选项#2 回答了这个问题。
也就是说,您最初的假设是有缺陷的。许多网站要求提供时区和 DST 的原因通常是因为他们的时区实现一开始就不支持 DST。他们所做的就是让你选择一个基本偏移量,并决定是否要在一年中的特定时间添加一个小时。他们可能称其为“时区”,但它绝不像 .Net 的类或像Noda TimeTimeZoneInfo这样的库那么强大。
如果您确实选择了“时区”,例如 by TimeZoneInfo.GetSystemTimeZones()(您应该保存Id属性并显示DisplayName属性),那么您绝对不应该询问用户是否使用 DST。如果用户居住在不使用夏令时的地方(例如亚利桑那州),则已经有一个选择。用户通常很擅长选择正确的选择来获得他们想要的效果,特别是如果他们居住在具有奇怪的夏令时规则的地区(例如印第安纳州)。
"America/New York"如果您使用 IANA/Olson 风格的时区(例如 ) ,无论它们是由Noda Time还是其他实现提供的,同样的想法也适用。您应该将 DST 决定委托给图书馆,而不是用户。
将其委托给图书馆的一个非常有效的论据是,这些 DST 规则可以更改,并且在其生命周期中的许多时刻都已更改。如果您正在编写处理过去信息的任何类型的应用程序或网站,您可能会发现今天有效的内容并不是对过去发生的事情的正确调整。此外,时区世界也有很多奇怪的地方,比如澳大利亚,某些地区的时差是 30 分钟而不是整整一个小时。您真的想自己管理这件事吗?可能不会。:)