0

你好!

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

我有三个问题

我必须问以防万一:DateTimeOffset.UtcNow无论服务器是否依赖夏令时,是否总是返回正确的 UTC 日期和时间?比如我第一次得到这个属性的值是夏令时前两分钟(或者是从夏令时转换回来之前),第二次是在2分钟后调用,那么所有属性的值是否案例仅相差 4 分钟?或者这里需要任何进一步的逻辑?(问题#1

请看下面的例子,告诉我你的想法。

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

然后用户打开一个带有新闻的页面,无论发布多久。这甚至可能在多年后发生。我没有要求他输入他的时区。相反,我使用以下 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 个字符)

Matt Johnson,感谢您提供如此详细的回答,尽管您不是第一次这样做。感谢您花时间解释这个特殊案例,而不仅仅是提供其他帖子的链接。

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

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

4

1 回答 1

0

回答问题 1

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

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

回答问题 2

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

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

回答问题 3

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

不,这不是正确的方法。你有几个选择:

第一个选项

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

警告,使用这种方法,由于我在此处描述的问题,某些转换可能不正确。

第二种选择

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

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

第三个选项

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

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

另外,请在以后的帖子中,一次只问一个问题。请在发帖前进行搜索——我之前已经多次以一种或另一种形式写过大部分内容

于 2013-10-19T02:17:39.497 回答