【问题标题】:VB.Net Convert time from UTC to LocalVB.Net 将时间从 UTC 转换为本地时间
【发布时间】:2019-03-04 18:51:02
【问题描述】:

我在一个新闻网站上工作,我正在以 UTC 格式保存数据库中的所有日期。然后,根据浏览器/机器的位置,我想相应地显示日期/时间(从UTC 转换为机器/浏览器的本地时间)。

首先,我想知道我是否按照应有的方式执行此操作(数据库中的 UTC 日期)。

其次,我想知道为什么在VB.NET 中这样做不那么简单?以下是我尝试过的方法,但都没有按需要起作用:

方法一:

TimeZoneInfo.ConvertTimeFromUtC

这会一直返回服务器时间,而不是客户端/机器时间。

方法2:

Dim TimeZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Middle East Standard Time")
Dim Dated As DateTime = TimeZoneInfo.ConvertTimeFromUtC(TempDate, TimeZone)

这有效,但未达到预期。这将数据库中的 UTC 日期/时间转换为 中东时区,但来自世界任何其他地方的任何用户都只能看到 中东时区中的日期/时间em> 而不是他所在的实际时区。另外,我不确定转换是否考虑 DayLightSaving

方法 3:

我尝试使用JavaScript 解决此问题。我创建了一个 cookie,它保存了 UTC 的 offset 并尝试在 VB.NET 中处理 offset 并进行转换。

<script>
    function setCookie(cname, cvalue, exdays) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires=" + d.toUTCString();
        document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
    }

    function getTimeOffset() {
        var offset = new Date().getTimezoneOffset();
        setCookie("_tz", offset);
    }
</script>  

JavaScripts 返回正确的 Offset,我将这个偏移量保存在 cookie 中。由于JavaScriptPage_Load 之后启动,我在Page_Init 上调用JavaScript 函数getTimeOffset()

ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "getTimeOffset();", True)

cookie 是在页面渲染之前创建的,并且 cookie 中存储的 offset 是正确的(这是我真正想要的!)。这里的问题是第一次加载。 VB.NET 在第一次加载时将 cookie 值读取为 空字符串。在第二个Page_Load 之后,VB.NET 读取 cookie 值并正确进行转换。

方法 4

尝试使用fiddle 中的所有示例获取偏移量,但偏移量始终为 0,这是错误的。

总结

我想知道VB.NET 中是否有任何我错过的功能来避免所有这些麻烦。将日期/时间从 UTC 转换为本地不是一件容易的事吗?

如果我做错了什么或者是否有更好的选择,请告诉我。

【问题讨论】:

  • 您可能会发现this DotNetHeaven article 很有用。我发现这是搜索词 vb.net get computer current time zone 的第一个 Google 搜索结果
  • 您的方法是正确的,但只需使用 DateTime.SpecifyKind。看看这个例子:dotnetfiddle.net/XxOiCb
  • 你可以在浏览器中完成。将日期时间渲染为 &lt;span&gt; 并将 data-time attribute 设置为 UTC 日期时间,然后使用 jQuery 将转换后的日期时间渲染到 $(document).ready 事件中的 span 的 innerHtml 中。或类似的东西。
  • @JeffZeitlin GetUtcOffset 返回 0,我比 UTC 早 2 小时。检查这个例子:dotnetfiddle.net/6aaF0a@David 我检查了这个例子,它返回 UTC 时间。我尝试放置 DateTimeKind.Local 而不是 DateTimeKind.Utc 但我仍然得到 UTC 时间。有什么建议吗? @AndrewMorton我想这是我在方法3中尝试过的,但适用于第二次重新加载而不是第一次。我想避免在第一次点击时重新加载页面。有什么明确的例子吗?

标签: vb.net datetime timezone utc timezone-offset


【解决方案1】:

您的后端代码对浏览器的时区一无所知。不管你使用什么语言,只有浏览器会知道用户的时区。

当 .Net 代码(无论是 VB 还是 C#)提到“本地”时,它表示代码运行所在的本地时区。换句话说,在 ASP.Net Web 应用程序中,这是您的服务器 的本地时区,而不是用户的本地时区。一般来说,服务器的本地时区通常是无关紧要的。

要实现您的目标,请将问题分成两部分。

  1. 在浏览器中获取用户的时区,发送到服务器。
  2. 使用传入的时区转换服务器上的时间。

对于第 1 步,请阅读 this answer 我发布到另一个问题。请注意,输出将是 IANA 时区标识符。不要传递数字偏移量,因为它没有携带足够的信息来正确转换不同的时间点(考虑夏令时和其他时区异常)。

对于第 2 步,您需要在以下方法之一中进行选择:

  • 如果您在非 Windows 操作系统上运行 .NET Core,或者在任何平台上运行 Noda Time 库,则可以将 IANA 时区标识符与 TimeZoneInfo 一起使用。

  • 您可以使用我的 TimeZoneConverter 库将 IANA 时区标识符转换为 Windows 时区标识符,然后您可以将结果与 Windows 上的 TimeZoneInfo 类一起使用。

一件小事:你使用了TimeZoneInfo.ConvertTimeToUtc,我认为你的意思是TimeZoneInfo.ConvertTimeFromUtc。注意转换的方向性。

我还要指出,还有一种替代方法,即将 UTC 时间戳一直传递到浏览器,然后在 JavaScript 中将 UTC 转换为本地时间。那么你根本不需要做任何时区检测。

【讨论】:

  • 感谢您的信息和建议。第1步:链接失效。您建议从浏览器获取时区并将其发送到服务器。在使用注册/登录功能时,这可能是一个很好的场景。但是,如果着陆页显示时间,则 JS 不会在 Page_Load 之前运行。这意味着该方法将从第二个 page_load 开始工作(如果我们使用会话/cookies)。第 2 步:我将执行测试并将答案标记为“已解决”,如果它有效。谢谢你!
  • 不知道为什么,但显然这个长期存在的问题刚刚被删除。 Here is another one that's similar。基本上你想打电话给Intl.DateTimeFormat().resolvedOptions().timeZone
猜你喜欢
  • 2018-07-27
  • 2012-02-29
  • 2014-07-18
  • 2021-02-04
  • 2010-09-15
  • 2011-05-01
  • 2019-04-30
  • 2017-03-20
相关资源
最近更新 更多