【问题标题】:Strange error with converting from UTC to TimeZone从 UTC 转换为 TimeZone 时出现奇怪的错误
【发布时间】:2021-04-28 17:45:23
【问题描述】:

我在将 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

我也想知道为什么我在美国服务器上的时间和波兰服务器上的时间不同。我在角度中使用管道来表示日期:'short':'UTC' 所以我应该从数据库中获取确切的日期而不需要本地转换,对吗?还是 C# 中的 DateTime 也将日期转换为服务器日期?

【问题讨论】:

  • 因为您使用的是正在更改时间的 ConvertTime。所有计算机都以 UTC 存储时间,然后在输入字符串或输出字符串时使用机器上的时区设置自动转换。当您使用 ConvertTime 时,您正在更改时间。波兰是+2,美国东部标准是-4。因此,如果是 UTC 午夜,则为美国东部标准时间晚上 8:00 和波兰时间凌晨 2:00。如果你去两台机器上并要求显示 UTC 时间,你会在两台机器上得到午夜。

标签: c# timezone


【解决方案1】:

参考the documentationTimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo)方法。

备注部分,它说如果源DateTimeKind 属性是DateTimeKind.Unspecified,则假定它是本地。由于您在代码中将 kind 显式设置为 Unspecified,因此您不会从 UTC 转换为指定时区,而是从本地时间转换为指定时区。

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

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

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

【讨论】:

  • 谢谢!我必须改变的唯一一件事是 ConvertTimeFromUtc。当我为我的问题寻找解决方案时,我不知道这种方法。此外,我将该错误更改为: DateTime localDateTime = Convert.ToDateTime(property.GetValue(value)); var localTime = LocalTimeConvert(locationTimeZone, localDateTime); property.SetValue(value, localTime);谢谢:)
猜你喜欢
  • 2016-07-29
  • 1970-01-01
  • 2011-09-29
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
  • 2016-07-22
相关资源
最近更新 更多