C# TimeZoneInfo在两位代码中的工作方式不同

C# TimeZoneInfo在两位代码中的工作方式不同,c#,timezone,C#,Timezone,我的UI层中有一些代码,它应该采用UTC格式的日期时间,并将其转换为本地日期时间: 在我的数据层中,我只需执行以下操作: private DateTime ConvertToLocal(DateTime dt) { if (_currentTimeZoneUser == string.Empty) { var u = new UserData(_userId).GetUser(_userId); _currentTimeZoneUser = u.T

我的UI层中有一些代码,它应该采用UTC格式的日期时间,并将其转换为本地日期时间:

在我的数据层中,我只需执行以下操作:

private DateTime ConvertToLocal(DateTime dt)
{
    if (_currentTimeZoneUser == string.Empty)
    {
        var u = new UserData(_userId).GetUser(_userId);
        _currentTimeZoneUser = u.TimeZoneId;
    }
    var reply = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dt, _currentTimeZoneUser);
    return reply;
}
这样做的目的是检查是否设置了_currentTimeZoneUser。如果没有,则从用户表中获取zimezone,然后进行转换

这段代码正在运行,我得到了一个有效的结果

然后我将代码复制到我的UI层(因为对于数据网格,我也需要在那里进行转换),但是“reply”总是等于“dt”

我在谷歌上搜索,发现我应该用一种稍微不同的方式来做。因此,我将UI方法更改为:

public static DateTime GetLocalDateTime(DateTime serverTime)
{
    var timeZoneId = HttpContext.Current.Session["TimeZoneId"].ToString();
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
    var reply = TimeZoneInfo.ConvertTimeFromUtc(serverTime, cstZone);
    return reply;
}
而且它有效

我不明白为什么它在我的数据层工作,但在UI中,我需要更改代码


我在其中一种方法中的时间转换代码是否有问题?

如果我理解正确,您的问题可以归结为
ConvertTimeBySystemTimeZoneId
ConvertTimeFromUtc
之间的差异

首先,您需要了解,任何涉及
DateTime
的时区转换操作都可能会有行为差异,具体取决于
DateTime
.Kind
值。当您查看每种方法(和)的文档时,您会发现一个图表,其中描述了三种不同类型(
Utc
Local
未指定的
)的行为

这是.Net中的一个痛处,这就是为什么存在类似的库。您可以在这两篇文章中阅读更多内容:

具体问题的实际原因可能是您传入了一个
DateTime
谁是
。Kind
未指定的
。在
ConvertTimeBySystemTimeZoneId
方法中,它将被视为
Local
,而在
ConvertTimeFromUtc
方法中,它将被视为
Utc

有两种解决办法

  • 第一个是您已经找到的-使用
    ConvertTimeFromUtc
    方法。您也应该在服务器代码中这样做

  • 第二种解决方案是在从数据库加载值时,将
    .Kind
    设置为
    Utc
    。在某些地方,您可能有这样的代码:

    foo.MyDateTime = (DateTime) dataReader["MyDateTime"]
    
    这将改变为:

    foo.MyDateTime = DateTime.SpecifyKind(
                       (DateTime) dataReader["MyDateTime"],
                       DateTimeKind.Utc);
    

我假设您正在使用
DataReader
响应进行直接ADO.Net调用。根据您实际正在做的事情进行相应调整。

这完全是错误的想法。当您使用HttpContext时,对本地时间感兴趣的唯一实体就是用户,数千英里,以及从web服务器上删除的不可用的时区数。在服务器端严格使用UTC,在浏览器中转换为本地时间。@HansPassant-这需要JavaScript,但这并不总是可能的,而且在这方面存在缺陷。在服务器端代码中进行时区转换没有错,只要您知道用户的时区id,他就是这样做的。