How to work with time zones in ASP.NET?
我正在开发一个"在线提醒系统"项目(ASP.NET 2.0(C)/SQL Server 2005)
因为这是一个提醒服务,它将在特定日期向用户发送邮件。但问题是,用户不是来自特定国家,而是来自世界各地和不同时区。现在,当我注册时,我要求用户使用时区,就像安装时Windows要求我们使用时区一样。
但是我不知道用户是否选择了(+5.30)或什么时区,那么如何在我的ASP.NET应用程序中处理这个时区。如何根据时区工作。
请建议是否有更好的方法来处理这个应用程序中的时区??
谢谢
首先,要确保您的数据位于哪个时区。我建议确保您存储的任何日期时间都存储在UTC时间中(使用
当您要为用户存储提醒时,您将需要当前的UTC时间,添加或删除用户的时区差异,并将新时间转换回UTC;这是您要在数据库中存储的内容。
然后,当您要检查要发送的提醒时,您只需根据UTC时间在数据库中查找要发送的提醒;基本上,获取所有具有时间戳的提醒,该时间戳在
更新一些实施细节:您可以从
1 2 3 4 | TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("<the time zone id>"); // May 7, 08:04:00 DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0); DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset); |
我建议在服务器端始终使用UTC(GMT)时间(代码隐藏、数据库等),并将时间从UTC转换为本地时间,仅用于显示目的。这意味着所有时间操作(包括在数据库中节省时间、执行计算等)都应该使用UTC完成。
问题是:您的代码隐藏如何知道客户机浏览器的时区?假设用户在表单中输入了一些日期/时间值(例如12/30/2009 14:30),并将其提交给服务器。假设用户提交了本地时间,服务器如何知道如何将该值转换为UTC?
应用程序可以要求用户指定时区(并将其保存在持久的cookie或数据库中),但它需要用户付出额外的努力,并且您的应用程序需要为此实现逻辑和屏幕。如果应用程序能自动确定客户端的时区,那就更好了。
我在javascript的getTimeZoneOffset函数的帮助下解决了这个问题,它是唯一一个可以告诉服务器客户端本地时间和GMT之间时间差的API。因为这是客户端API,所以我做了以下操作:在服务器端检查保存时间偏移值的自定义会话cookie,如果它s不可用,重新加载页面(仅在get调用期间,而不是post调用期间),添加一些javascript逻辑以生成时间偏移量并将其保存在cookie中。从客户端来看,这几乎是透明的(在会话期间,我会在GET上重新加载一个页面)。一旦我在cookie中有了偏移量,我就会根据时间转换的方向(UTC到本地时间,或本地时间到UTC)将其应用到时间管理功能中。
这听起来可能有点复杂,但在我编写助手函数之后,将这个功能集成到站点中只需要在页面加载(需要时间转换的页面)中进行一次调用,并在向浏览器发送和检索时间值时使用时间转换例程。下面是一个如何使用它的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | using My.Utilities.Web; ... // Derive the form class from BaseForm instead of Page. public class WebForm1: BaseForm { ... private void Page_Load(object sender, System.EventArgs e) { // If we only want to load the page to generate the time // zone offset cookie, we do not need to do anything else. if (InitializeLocalTime()) return; // Assume that txtStartDate is a TextBox control. if (!IsPostback) { // To display a date-time value, convert it from GMT (UTC) // to local time. DateTime startDate = GetStartDateFromDB(...); txtStartDate.Text = FormatLocalDate(startDate); ... } else { // To save a date-time value, convert it from local // time to GMT (UTC). DateTime tempDate = DateTime.Parse(txtStartDate.Text); DateTime startDate = ConvertLocalTimeToUtc(tempDate); SaveStartDateInDB(startDate, ...); ... } } ... } |
如果您需要更详细的信息,请查看关于时间的信息:在ASP.NET应用程序文章中本地化时间(很抱歉,但我没有到发布者网站上文章的直接链接,因为ASP.NetPro仅限制对付费订户的访问;但是有到PDF副本的链接)。我希望我可以发布文章中的示例,但我不想侵犯版权;但是,这里有一个项目来构建一个具有所有必要功能和文档的助手库(忽略您不需要的东西)。
更新:这篇文章已经由新的发布者在网上发布了示例项目。
到目前为止,所有答案的问题在于,他们没有考虑到普拉尚特正在努力实现的目标。如果在夏令时更改前一天的系统用户的偏移量为+12,并为第二天设置了提醒,则应触发提醒时的偏移量将为+13。
这就是为什么您只能对正在发生的事情使用当前偏移量的原因。尽管我同意所有其他人的观点,但服务器端(可能仅用于显示的服务器端除外)应始终存储在UTC中。
如果您在Framework 2.0或更高版本上,您可能希望使用datetimeoffset结构而不是datetime。
datetimeoffset表示相对于UTC时间的时间点,因此在这种情况下应该更容易处理。
有两个步骤:
使用javascript在客户端检测不同的时区:
1
2然后在服务器端,C代码根据检测到的上述时区偏移量将服务器时间转换为客户端时间:
--------------------;
1 2 3 4 5 6 | string queryStr = Request.QueryString["diffInMinutes"]; int diffInMinutes = 0; if (Int32.TryParse(queryStr, out diffInMinutes)) { clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes); } |
问题是,与UTC的时差在一年中的不同时间会有所不同——每个时区都有自己的规则。(在开发会议室调度应用程序时,我学到了这一点。)
似乎有内置支持:http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx
我自己也没试过,但它似乎保证了正确的转换,为夏令时节省了费用。
如果没有,这里有一个(昂贵的)商业工具我已经使用:http://www.worldtimeserver.com/time_zone_guide/
基本上,您需要做的就是将偏移量(小时+分钟)添加到用户输入的本地时间。加入偏移量基本上会给您一个以UTC(基本上是格林威治标准时间)时区为单位的日期时间。
通常最容易将所有时间标准化为UTC,这样应用程序逻辑就不必处理偏移量。
本页有几个好例子:http://msdn.microsoft.com/en-us/library/bb546099.aspx