我将所有DateTime字段存储为UTC时间。当用户请求网页时,我想获取他首选的本地时区(而不是服务器计算机的本地时区),并自动将所有Web表单中的所有DateTime字段显示为本地日期。
当然,我可以将转换应用于每种格式的每个DateTime.ToString()调用或实现一些帮助器实用程序,但这是一项耗时的任务,并且还有一些第三方组件很难配置自定义DateTime显示模板。
本质上,我想使DateTime类的行为如下:
from this moment on for this web request,
whenever some code calls DateTime.ToString(), convert it to the local time
using the timezone offset given at the very beginning of the web request,
but if possible, please keep .NET core library DateTime.ToString() calls intact
(I don't want to mess up event logging timestamps etc.)
有什么办法吗?
顺便说一句,如果有问题,我正在使用ASP.NET MVC 4。
最佳答案
您不能直接做您想要的,但是我会建议一些替代方法。正如Nicholas指出的那样,HTTP中没有任何内容可以直接为您提供时区。
选项1
TimeZoneInfo
类访问的Microsoft时区,或者世界其他地方使用的IANA / Olson时区。 Read here for more info。我的建议是使用NodaTime提供的实现。 moment.tz.guess()
进行此操作。 DateTime
值转换为该本地时区。不幸的是,您无法在线程上进行任何设置。更改系统时区时,它对于所有进程和线程都是全局的。因此,您别无选择,只能将时区传递回您要发送的每个地方。 (我相信这是您的主要问题。)See this almost duplicate here. DateTime.ToString()
方法。这不会进行任何时区转换-只是确保数字在正确的位置,使用正确的分隔符,并为工作日或月份的名称提供适当的语言。 选项2
根本不要将其转换为服务器上的本地时间。
.Kind
属性为Utc
。从数据库加载时,可能应该执行此操作,但是如果需要,可以手动执行此操作:myDateTime = DateTime.SpecifyKind(myDateTime, DateTimeKind.Utc);
myDateTime.ToString("o"); // example: "2013-05-02T21:01:26.0828604Z"
Date
对象,如下所示:var dt = new Date('2013-05-02T21:01:26.0828604Z');
但是,这仅在支持ISO-8601格式的较新的浏览器中有效。相反,我建议使用moment.js库。它在不同的浏览器中是一致的,并且对ISO日期和本地化提供了更好的支持。另外,您还获得了许多其他有用的解析和格式化功能。
// pass the value from your server
var m = moment('2013-05-02T21:01:26.0828604Z');
// use one of the formats supported by moment.js
// this is locale-specific "long date time" format.
var s = m.format('LLLL');
选项1的优点是您可以使用任何时区中的时间。如果您可以从下拉列表中询问用户的时区,则您无需使用任何Javascript。
选项2的优点在于,您可以让浏览器为您完成一些工作。如果要发送原始数据,例如对WebAPI进行AJAX调用,这是最好的方法。但是,JavaScript仅知道UTC和浏览器的本地时区。因此,如果您需要转换到其他区域,它将无法正常工作。
您还应该注意,如果选择选项#2,则可能会受到ECMAScript 5.1设计缺陷的影响。如果要处理的日期与当前生效的夏令时规则集不同,则此方法会起作用。您可以阅读更多in this question和on my blog。
如果我们在HTTP header 中包含一些时区信息,那么会容易得多,但是不幸的是我们没有。这是许多困难,但这是兼具灵活性和准确性的最佳方法。