我已经看到许多网站(通常是论坛)允许用户通过选择以下内容来指定其TimeZone首选项:
据我所知,.NET在进行转换时总是考虑DST,因此问题是:
如何在C#中实现“不使用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);
}
该测试通过,表明:接下来,我注意到
TimeZoneInfo.GetAdjustmentRules()
方法返回了 AdjustmentRule
对象数组,并且发现如果取消这些规则的效果,我可以获得DST不受影响的值。所以我写了下面的方法,如果
DateTime
对象is affected by 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)。在记下来的同时,我想到了另一个可行的想法:不用任何
TimeZoneInfo.Convert...()
方法,只需将roTimezone.BaseUtcOffset
添加到UTC日期即可。任何人都可以指出执行此操作的正确方法吗?
最佳答案
解析您的问题,似乎您有两个建议的解决方案:
DateTime
并添加BaseUtcOffset
,以便您始终处理标准时间。 由于您的问题是如何不实现DST,我想说您自己使用选项#2回答了它。
就是说,您最初的假设是有缺陷的。许多站点要求提供时区和DST的原因通常是因为其时区实现一开始不支持DST。他们正在做的是让您选择一个基本偏移量,然后决定是否要在一年的设定时间内添加一个小时。他们可能将其称为“时区”,但它绝对不比.Net的
TimeZoneInfo
类或诸如Noda Time之类的库健壮。如果您确实是在选择“时区”(例如
TimeZoneInfo.GetSystemTimeZones()
)(应保存Id
属性并显示DisplayName
属性),则绝对不应询问用户是否使用DST。如果用户居住在不使用DST的地方(例如在亚利桑那州),则已经有选择。用户通常会选择正确的选项来获得所需的效果,特别是如果他们居住在DST规则异常的地区(例如印第安纳州),则用户通常会非常擅长。如果您使用的是IANA/Olson风格的时区(例如
"America/New York"
),无论是Noda Time还是其他实现方式,都适用相同的想法。您应该将DST决定委托(delegate)给库-而不是用户。将其委托(delegate)给库的一个非常有效的论据是,这些DST规则可以更改,并且在其生命周期的许多点上都已更改。如果您正在编写处理过去信息的任何类型的应用程序或站点,则可能会发现今天有效的内容并不是对过去发生的内容的正确调整。另外,在时区世界中也有很多怪异之处,例如澳大利亚,其中某些地区的时间间隔是30分钟而不是一小时。您真的要自己管理吗?可能不会。 :)
关于c# - 从DateTime删除DST,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12266948/