将DateTime表示为远程用户的本地

时间:2013-10-17 21:28:49

标签: c# javascript datetimeoffset timezone-offset localtime

您好!

我对时区的问题感到困惑。我正在编写一个Web应用程序,其中包含一些发布日期的新闻,我希望客户以相应的本地时间的形式查看新闻发布日期。但是,我不知道客户所在的时区。

我有三个问题

我不得不问以下: DateTimeOffset.UtcNow 始终返回正确的UTC日期和时间,无论服务器是否依赖于夏令时时间?例如,如果我第一次在夏令时之前(或从夏令时返回之前)获得此属性的值两分钟,并且在传输之后的2分钟内获得第二次,则是否所有属性的值都是案件相差仅4分钟?或者这需要任何进一步的逻辑? (问题#1

请参阅以下示例并告诉我您的想法。

我在网站上发布了这条消息。我假设DateTimeOffset.UtcNow考虑了服务器的时区和夏令时,所以当按下“提交”按钮时,我立即得到正确的UTC服务器时间。我将此值写入类型为 datetime2(0)的字段中的MS SQL数据库。

然后,无论发布后多长时间,用户都会打开包含新闻的页面。多年后甚至可能发生这种情况。我没有让他进入他的时区。相反,我使用javascript函数按照以下方式从UTC获得当前本地时间的偏移量:

function GetUserTimezoneOffset()
{
    var offset = new Date().getTimezoneOffset();
    return offset;
}

接下来,我计算出版的日期和时间,这将显示用户:

public static DateTime Get_Publication_Date_In_User_Local_DateTime(
    DateTime Publication_Utc_Date_Time_From_DataBase,
    int User_Time_Zone_Offset_Returned_by_Javascript)
{
    int userTimezoneOffset = User_Time_Zone_Offset_Returned_by_Javascript; // For
        // example Javascript returns a value equal to -300, which means the
        // current user's time differs from UTC to 300 minutes. Ie offset
        // is UTC +6. In this case, it may be the time zone UTC +5 which
        // currently operates summer time or UTC +6 which currently operates the
        // standard time.
        // Right? (Question #2)

    DateTimeOffset utcPublicationDateTime =
        new DateTimeOffset(Publication_Utc_Date_Time_From_DataBase,
            TimeSpan.Zero); // get an instance of type DateTimeOffset for the
                // date and time of publication for further calculations

    DateTimeOffset publication_DateTime_In_User_Local_DateTime =
       utcPublicationDateTime.ToOffset(new TimeSpan(0, - userTimezoneOffset, 0));

    return publication_DateTime_In_User_Local_DateTime.DateTime;// return to user
}

获得的值是否正确?这是解决这个问题的正确方法吗? (问题#3

10月19日6:58更新 (我尝试将其发布为评论,但它太长了668个字符)

马特约翰逊,谢谢,尽管你这样做不是第一次这样详细的回答。 谢谢:花时间解释这个特例,而不只是提供其他帖子的链接。

我已阅读您提供的信息。也许我还没有完全了解所有的细节,但是如果我理解正确的话,对于从UTC到同一用户的那一刻,DateTime(多年前在数据库中写的)的正确转换,我需要知道UTC他那时的偏移量。并且考虑到DST的转移规则不断变化是很困难的。即使是现在,虽然平台“.NET”包含一些用于TimeZoneInfo类型的TZDB,但如果没有用户的确切位置,我就无法利用它。

但是,如果我只对今年开始的日期和时间感兴趣,并且仅在2011年取消DST的俄罗斯?据我了解,这意味着如果位于俄罗斯的用户计算机上的时钟配置正确,这种方法将始终给出正确的结果。自2011年以来,用户时钟的UTC偏移应始终相同。因此,不同浏览器中的移位指示器对于俄罗斯用户来说不会有所不同。

1 个答案:

答案 0 :(得分:0)

回答问题1

  

...无论服务器是否依赖夏令时,DateTimeOffset.UtcNow总是会返回正确的UTC日期和时间吗?

是。只要您的时钟设置正确,UtcNow始终指的是UTC时间。服务器的时区设置不会影响它。无论DST如何,示例中的值始终为4分钟。

回答问题2

var offset = new Date().getTimezoneOffset();

由于new Date()会返回当前日期和时间,因此会返回当前偏移量。然后,继续将此当前偏移应用于某个过去值,该值可能是或可能不是该特定时间的正确偏移量。请阅读the timezone tag wiki,尤其是标题为“时区!=偏移”的部分。

回答问题3

  

获得的值是否正确?这是解决这个问题的正确方法吗?

没有。这不是正确的方法。您有几个选择:

第一个选项

  • 只需将UTC值传递给JavaScript,无需修改。
  • 以ISO8601格式发送,例如2013-10-18T12:34:56.000Z。您可以使用yourDateTime.ToString("o")轻松地在.Net中获取此信息。
    • 请确保您开始的DateTime.Kind == DateTimeKind.Utc,否则最终无法获得Z,这是必不可少的。
    • 如果您要定位无法解析ISO8601的旧版浏览器,那么您需要一个像moment.js这样的库来为您解析它。
  • 或者,您可以将自1970年1月1日UTC以来的毫秒数作为数字传递,并将其加载到JavaScript Date中而不是解析。
  • 现在您只需使用JavaScript显示Date对象即可。让浏览器将其从UTC转换为用户本地时间。

警告,使用此方法,由于the problem I describe here,某些转化可能不正确。

第二个选项

  • 与第一个选项一样,将UTC时间戳传递给JavaScript
  • 使用它来获取该时间戳的偏移
  • 在回发或ajax调用中将偏移量传回服务器。
  • 在服务器上应用偏移量
  • 输出当地时区

由于往返,我不特别喜欢这个选项。您可以像在第一个选项中一样在JavaScript中计算它。

第三个选项

  • 获取用户的时区。最好的方法是通常在用户设置页面上询问它们。
  • 使用它在服务器上完全从UTC时间转换为当地时间。
  • 您可以使用Windows时区和TimeZoneInfo课程进行转换。
  • 或者您可以使用IANA / Olson时区和Noda Time库。

这种方法更准确,但需要更多用户互动。

另外,请在以后的帖子中,一次只询问一个问题。请在发布之前进行搜索 - 之前我已经用一种或多种多次时间写了大部分内容。