将DateTime.Now转换为不同的时区

这段代码已经工作了很长时间,但是当我尝试将DateTime.Now作为outageEndDate参数传递时,现在已经破了:

public Outage(DateTime outageStartDate, DateTime outageEndDate, Dictionary weeklyHours, string province, string localProvince) { this.outageStartDate = outageStartDate; this.outageEndDate = outageEndDate; this.weeklyHours = weeklyHours; this.province = province; localTime = TimeZoneInfo.FindSystemTimeZoneById(timeZones[localProvince]); if (outageStartDate < outageEndDate) { TimeZoneInfo remoteTime = TimeZoneInfo.FindSystemTimeZoneById(timeZones[province]); outageStartDate = TimeZoneInfo.ConvertTime(outageStartDate, localTime, remoteTime); outageEndDate = TimeZoneInfo.ConvertTime(outageEndDate, localTime, remoteTime); 

我在最后一行得到的错误消息是在DateTime参数(outageEndDate)上没有正确设置Kind属性。 我用谷歌搜索并检查了SO的例子,但我真的不明白错误信息。

任何建议表示赞赏。

问候。

编辑 – 确切的错误消息是:

 The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local. Parameter name: sourceTimeZone 

编辑:outageEndDate.Kind = Utc

谢谢你澄清了你的问题。

如果DateTime实例KindLocal ,则TimeZoneInfo.ConvertTime将期望第二个参数是您计算机的本地时区。

如果DateTime实例KindUtc ,则TimeZoneInfo.ConvertTime将期望第二个参数是Utc时区。

您需要先将outageEndDate转换为正确的时区,以防localAdvice时区与您计算机上的时区不匹配。

 outageEndDate = TimeZoneInfo.ConvertTime(outageEndDate, localTime); 

这是你可以尝试的一个例子

这取决于你所说的“GMT + 1时区”。 你的意思是永久UTC + 1,或者你的意思是UTC + 1还是UTC + 2,具体取决于夏令时?

如果您使用的是.NET 3.5,请使用TimeZoneInfo获取适当的时区,然后使用:

 // Store this statically somewhere TimeZoneInfo maltaTimeZone = TimeZoneInfo.FindSystemTimeZoneById("..."); DateTime utc = DateTime.UtcNow; DateTime malta = TimeZoneInfo.ConvertTimeFromUtc(utc, maltaTimeZone ); 

您需要计算出马耳他时区的系统ID,但您可以通过在本地运行此代码轻松完成此操作:

 Console.WriteLine(TimeZoneInfo.Local.Id); 

如果您使用.NET 3.5,则需要自己计算夏令时。 说实话, 最简单的方法是成为一个简单的查找表。 计算出未来几年的DST变化,然后编写一个简单的方法,在特定的UTC时间返回偏移量,并对该列表进行硬编码。 您可能只想要一个带有已知更改的已排序List ,并在您的日期在最后一次更改之后交替1到2小时:

 // Be very careful when building this list, and make sure they're UTC times! private static readonly IEnumerable DstChanges = ...; static DateTime ConvertToLocalTime(DateTime utc) { int hours = 1; // Or 2, depending on the first entry in your list foreach (DateTime dstChange in DstChanges) { if (utc < dstChange) { return DateTime.SpecifyKind(utc.AddHours(hours), DateTimeKind.Local); } hours = 3 - hours; // Alternate between 1 and 2 } throw new ArgumentOutOfRangeException("I don't have enough DST data!"); }