将日期时间表示为远程用户的本地用户
本文关键字:用户 程用户 时间 日期 时间表 表示 | 更新日期: 2023-09-27 18:35:47
你好!
我对时区问题感到困惑。我正在编写一个 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 个字符)
马特·约翰逊,谢谢你如此详细的回答,尽管你不是第一次这样做。感谢您花时间解释这个特殊案例,而不仅仅是提供其他帖子的链接。
我已阅读您提供的信息。也许我仍然没有完全了解所有细节,但是如果我理解正确,对于 DateTime(多年前在数据库中编写的)从 UTC 到同一用户时刻的正确转换,我需要知道他当时拥有的 UTC 偏移量。而且很难考虑到DST的传输规则不断变化。即使是现在,尽管平台".NET"包含一些用于TimeZoneInfo类型的TZDB,但如果没有用户的确切位置,我就无法利用它。
但是,如果我只对今年开始的日期和时间感兴趣,并且只对 2011 年取消 DST 的俄罗斯感兴趣怎么办?据我了解,这意味着如果在位于俄罗斯的用户计算机上正确配置时钟,这种方法将始终给出正确的结果。自 2011 年以来,用户时钟对 UTC 的偏移量应始终相同。因此,对于俄罗斯用户来说,不同浏览器中的换档指示器不会有所不同。
回答问题 1
。
DateTimeOffset.UtcNow
是否始终返回正确的 UTC 日期和时间,无论服务器是否依赖于夏令时?
是的。 只要您的时钟设置正确,UtcNow
始终是指 UTC 时间。 服务器的时区设置不会影响它。 无论 DST 如何,示例中的值将始终为 4 分钟。
对问题2的回答
var offset = new Date().getTimezoneOffset();
由于new Date()
返回当前日期和时间,这将返回当前偏移量。 然后,继续将此电流偏移应用于某个过去的值,该值可能是也可能不是该特定时间的正确偏移量。 请阅读时区标签维基,特别是标题为"时区!=偏移量"的部分。
对问题3的回答
获得的值是否正确?这是解决这个问题的正确方法吗?
不。 这不是正确的方法。 您有以下几种选择:
第一个选项
- 只需将 UTC 值传递给 JavaScript 而不加修改即可。
- 以ISO8601格式发送,例如
2013-10-18T12:34:56.000Z
. 您可以使用yourDateTime.ToString("o")
在 .Net 中轻松获取此信息。- 确保您开始使用的
DateTime
具有.Kind == DateTimeKind.Utc
,否则它不会在最后获得Z
,这是必不可少的。 - 如果您的目标是无法解析ISO8601的旧浏览器,那么您将需要像 moment.js 这样的库来为您解析它。
- 确保您开始使用的
- 或者,您可以将自 1/1/1970 UTC 以来的毫秒数作为数字传递,并将其加载到 JavaScript
Date
而不是解析中。 - 现在,您可以使用 JavaScript 显示
Date
对象。 让浏览器将其从 UTC 转换为用户本地时间。
警告,使用此方法,由于我在此处描述的问题,某些转换可能不正确。
第二种选择
- 与第一个选项一样,将 UTC 时间戳传递给 JavaScript
- 使用它来获取该时间戳的偏移量。
- 在回发或 ajax 调用中将偏移量传递回服务器。
- 在服务器上应用偏移量
- 输出本地时区
由于往返,我不是特别喜欢这个选项。 你不妨像第一个选项一样在 JavaScript 中计算它。
第三种选择
- 获取用户的时区。最好的方法是向他们询问,通常在用户设置页面上。
- 使用它完全在服务器上从 UTC 时间转换为本地时间。
- 您可以使用 Windows 时区和
TimeZoneInfo
类进行转换。 - 或者您可以使用 IANA/Olson 时区和 Noda 时间库。
- 如果执行此操作,则可以选择使用基于地图的时区选取器。
- 您可以使用jsTimeZoneDetect猜测用户的时区。
此方法更准确,但需要更多的用户交互。
另外,请在以后的帖子中,一次只问一个问题。 请在发布之前搜索 - 我之前已经以一种或另一种形式写了很多次。