2013-08-17 28 views
2

两位我有我的UI层,这是应该采取一个DateTime,这是UTC一些代码,并将其转换为本地日期时间:的TimeZoneInfo的工作方式不同的代码

在我的数据层,我只是这样做:

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层(因为我还需要为数据网格进行转换),但'回复'总是等于'dt'。

我用Google搜索了一下,发现我应该以一种稍微不同的方式做。所以我改变我的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中,我需要更改代码。

我是否在我的时间转换代码中的一种方法做错了什么?

+0

这完全是错误的。当你使用HttpContext时,那些对当地时间感兴趣的* only *实体就是用户,几千英里的距离以及从你的Web服务器中删除的无法估量的时区数量。在服务器端严格使用UTC,在浏览器中转换为本地时间。 –

+1

@HansPassant - 这需要JavaScript,这并不总是可能的,并且在这方面有错误[在转换过去的日期时](http://codeofmatt.com/2013/06/07/javascript-date-type-is-可怕破碎/)。在服务器端代码中进行时区转换没有任何问题,只要您知道用户的时区标识,他就可以。 –

回答

1

如果我正确地理解你,你的问题归结为ConvertTimeBySystemTimeZoneIdConvertTimeFromUtc之间的差异。

首先,您需要了解的是,涉及DateTime的任何时区转换操作可能会有行为差异,具体取决于您给出的的.Kind的值。当您查看每种方法(herehere)的文档时,可以找到一张图表,描述三种不同类型(Utc,Local,Unspecified)的行为。

这是.Net中的一个痛点,这就是为什么像Noda Time这样的库存在。您可以在这两篇文章中了解更多:

的实际原因的具体问题是,你可能在一个DateTime谁的.KindUnspecified通过。在ConvertTimeBySystemTimeZoneId方法中,这将被视为是Local,而在ConvertTimeFromUtc方法中,它将被视为是Utc

有两种解决方案。

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

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

    foo.MyDateTime = (DateTime) dataReader["MyDateTime"] 
    

    这将改变这样的:

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

我假设你正在做一个DataReader响应直接ADO.Net通话。无论你在做什么,都要相应调整。

相关问题