从 UTC 转换为 TimeZone 时出现奇怪错误

Strange error with converting from UTC to TimeZone

我在从 UTC 时间转换为相应本地时间时遇到问题。

我拥有的是字符串形式的 UTC 时间和位置时区(如“东部标准时间”)。

我的代码:

private static DateTime? LocalTimeConvert(string locationTimeZone, DateTime? dateTimeUtc)
{

    var dateTimeUnspec = DateTime.SpecifyKind(dateTimeUtc.Value, DateTimeKind.Unspecified);
    DateTime utcDateTime = TimeZoneInfo.ConvertTime(dateTimeUnspec, TimeZoneInfo.FindSystemTimeZoneById(locationTimeZone));

    return utcDateTime;
}

public static T LocalTime<T>(T value, string locationTimeZone)
{
    if (value.GetType().IsGenericType && value.GetType().GetGenericTypeDefinition() == typeof(List<>))
    {
        IList collection = (IList)value;

        foreach (var element in collection)
        {
            VariableConvertion(element, locationTimeZone);
        }
    }
    else
    {
        VariableConvertion(value, locationTimeZone);
    }

    return value;
}


private static T VariableConvertion<T>(T value, string locationTimeZone)
{
    PropertyInfo[] props = value.GetType().GetProperties();

    foreach (var property in props)
    {
        if (property.PropertyType == typeof(DateTime?) || property.PropertyType == typeof(DateTime))
        {
            if (property.GetValue(value) != null)
            {
                var localTime = LocalTimeConvert(locationTimeZone, DateTime.Parse(property.GetValue(value).ToString()));
                property.SetValue(value, localTime);
            }
        }
    }

    return value;
}

假设进入该方法的任何值都是搜索日期变量并用适当的本地时间更改它们。

不幸的是,我有一个奇怪的错误,它一次正确转换而另一次错误。

来自 LocalTimeConvert 方法的数据:

东部标准时间 - 正确

    System.TimeZoneInfo.FindSystemTimeZoneById returned {(UTC-05:00) Stany Zjednoczone i Kanada (czas wschodni)}    System.TimeZoneInfo
    locationTimeZone    "Eastern Standard Time" string
    dateTimeUtc {19.03.2021 15:43:07}   System.DateTime?
    dateTimeUnspec  {19.03.2021 15:43:07}   System.DateTime
    utcDateTime {19.03.2021 10:43:07}   System.DateTime

欧洲中部标准时间 - 不正确

    System.TimeZoneInfo.FindSystemTimeZoneById returned {(UTC+01:00) Sarajewo, Skopie, Warszawa, Zagrzeb}   System.TimeZoneInfo
    locationTimeZone    "Central European Standard Time"    string
    dateTimeUtc {22.03.2021 12:58:09}   System.DateTime?
    dateTimeUnspec  {22.03.2021 12:58:09}   System.DateTime
    utcDateTime {22.03.2021 12:58:09}   System.DateTime

我也想知道为什么我在美国服务器上的时间和在波兰服务器上的时间不同。我在 angular 中使用管道作为日期:'short': 'UTC' 所以我应该在没有本地转换的情况下从数据库中获取准确的日期,对吗?或者 C# 中的 DateTime 也将日期转换为服务器日期?

参考TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo)方法的the documentation

Remarks部分说如果源DateTimeKind属性是DateTimeKind.Unspecified,假设它是 local。由于您在代码中明确地将种类设置为 Unspecified,因此您不会从 UTC 转换为命名时区,而是从本地时间转换为命名时区。

在此上下文中,“本地时间”是指执行代码的计算机的时区设置的本地时间。因此,如果您在波兰的服务器设置为波兰时区,则无法转换为波兰时间。

如果您打算将 UTC 转换为特定时区,那么源值的 Kind 应该是 DateTimeKind.Utc,或者您应该使用 ConvertTimeFromUtc 而不是 [=18] =](不同之处在于,Unspecified kind 被假定为 Utc 而不是 Local)。

顺便说一句 - DateTime.Parse(property.GetValue(value).ToString() 有一个潜在的错误。永远不要从一个对象创建一个字符串只是为了再次将它解析回一个对象。相反,cast 将对象拆箱为所需的类型。 tostring/parse 方法通常较慢,并且经常引入与当前文化的日期格式相关的错误。