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

时间:2012-08-08 20:52:12

标签: c# datetime

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

public Outage(DateTime outageStartDate, DateTime outageEndDate, Dictionary<string, string> 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

2 个答案:

答案 0 :(得分:8)

感谢您澄清问题。

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

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

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

outageEndDate = TimeZoneInfo.ConvertTime(outageEndDate, localTime);

答案 1 :(得分:1)

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

这取决于“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<DateTime>,并且在您的日期是最后一次更改之后的1到2小时之间交替:

// Be very careful when building this list, and make sure they're UTC times!
private static readonly IEnumerable<DateTime> 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!");
}