我正在新闻网站上工作,并将所有日期保存在UTC中的数据库中。然后,根据浏览器/机器的位置,我想相应地显示日期/时间(从UTC
转换为机器/浏览器的本地时间)。
首先,我想知道是否以这种方式进行操作(数据库中的UTC日期)。
第二,我想知道为什么在VB.NET
中这样做不是那么简单吗?以下是我尝试过的方法,但没有按需使用的方法:
方法1:
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
返回正确的偏移量,我将此偏移量保存在 cookie 中。由于JavaScript
在Page_Load
之后启动,因此我在JavaScript
上调用getTimeOffset()
函数Page_Init
:
ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "getTimeOffset();", True)
cookie 是在呈现页面之前创建的,并且存储在 cookie 中的偏移量是正确的(这是我真正想要的!)。这里的问题是第一次加载。 VB.NET
在第一次加载时将 cookie 值读取为空字符串。从第二Page_Load
开始,VB.NET
读取cookie值并正确进行转换。
方法4
尝试使用此fiddle中的所有示例来获取偏移量,但偏移量始终为0,这是错误的。
摘要
我想知道在VB.NET
中是否缺少任何功能来避免所有麻烦。将日期/时间从UTC转换为本地不是一件容易的事吗?
请告诉我我做错了什么还是有更好的选择。
答案 0 :(得分:1)
您的后端代码对浏览器的时区一无所知。不管使用哪种语言,只有浏览器才能知道有关用户所在时区的任何信息。
当.Net代码(无论VB或C#)指的是“本地”时,表示该代码运行所在的本地时区 。换句话说,在ASP.Net Web应用程序中,这是您的服务器而不是用户的本地时区。一般来说,服务器的本地时区通常是无关紧要的。
要实现目标,请将问题分为两部分。
对于步骤1,请阅读我发布到另一个问题的this answer。请注意,输出将是IANA时区标识符。不要传递数字偏移量,因为它没有足够的信息来正确转换不同的时间点(考虑夏时制和其他时区异常)。
对于步骤2,您需要在以下方法之一中进行选择:
如果您在非Windows操作系统上运行.NET Core,或者在任何平台上与Noda Time库一起使用,则可以将IANA时区标识符与TimeZoneInfo
一起使用。< / p>
您可以使用我的TimeZoneConverter库将IANA时区标识符转换为Windows时区标识符,然后可以在Windows上的TimeZoneInfo
类中使用结果。
一件小事情:您使用过TimeZoneInfo.ConvertTimeToUtc
,我想您的意思是TimeZoneInfo.ConvertTimeFromUtc
。注意转换的方向性。
我还将指出,还有一种替代方法,就是将UTC时间戳一直传递到浏览器,然后在JavaScript中将UTC转换为本地时间。然后,您根本不需要执行任何时区检测。