如何在ASP.NET中使用时区?
我正在开发一个“在线提醒系统”项目(ASP.NET 2.0(C#)/ SQL Server 2005)
因为这是一个提醒服务,将邮件发送到特定date的用户。 但问题是用户不是来自特定的国家,他们来自世界各地,来自不同的时区。 现在当我注册的时候,我要求用户使用时区的方式和Windows安装时候的时区一样。
但我没有得到如果用户select(+5.30)或什么时区,然后如何处理我的asp.net应用程序中的这个时区。 如何根据时区工作。
如果有更好的方法来处理这个应用程序的时区,请提出build议?
谢谢
首先要确定你的数据在哪个时区。我build议确保你存储的任何DateTime以UTC时间存储(使用DateTime.ToUniversalTime()
来获取它)。
当您要为用户存储提醒时,您将需要当前的UTC时间,添加或删除用户的时区差异,并将该新时间转换回UTC; 这是你想要存储在数据库中。
然后,当你想检查发送的提醒时,根据UTC时间,你只需要在数据库中查看现在发送的提醒; 基本上得到所有提醒都有DateTime.Now.ToUniversalTime()
之前的时间戳。
更新一些实现细节:您可以从TimeZoneInfo.GetSystemTimeZones()
方法获取时区列表; 您可以使用这些来显示用户的时区列表。 如果您存储所选时区的Id
属性,则可以从中创buildTimeZoneInfo类实例,并计算给定本地date/时间值的UTC时间:
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);
我build议在服务器端 (代码隐藏,数据库等)总是使用UTC(GMT)时间 ,并将时间从UTC转换为本地时间,仅用于显示目的 。 这意味着所有的时间操作 – 包括在数据库中存储时间,执行计算等 – 都应该使用UTC来完成。
问题是:你的代码隐藏是如何知道客户端浏览器的时区是什么? 假设用户在表单中input一些date/时间值(如12/30/2009 14:30 )并提交给服务器。 假设用户提交本地时间,服务器如何知道如何将此值转换为UTC?
应用程序可以要求用户指定时区(并将其保存在持久cookie或数据库中),但是它需要用户付出额外的努力,并且您的应用程序需要为此执行逻辑和屏幕。 如果应用程序可以自动确定客户端的时区将会更好。
我已经在JavaScript的getTimezoneOffset函数的帮助下解决了这个问题,它是唯一可以告诉服务器关于客户端本地时间和GMT之间的时间差的API。 由于这是一个客户端API,我做了以下事情:在服务器端检查保存时间偏移值的自定义会话cookie,如果它不可用,重新加载页面(仅在GET期间,而不是POST,调用)添加了一些JavaScript逻辑来生成时间偏移并将其保存在cookie中。 从客户端来看,这几乎是透明的(一次在会话期间我重新加载页面上的GET)。 一旦我在Cookie中有偏移量,我就会根据时间转换的方向(UTC到当地时间或本地时间到UTC)将它应用到时间pipe理function。
这可能听起来有些复杂,但是在我写了帮助函数之后,把这个特性集成到网站中就是在Page_Load中(需要时间转换的页面)进行一次调用 ,在发送时使用时间转换例程并从浏览器中检索时间值。 这是一个如何使用它的例子:
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链接的链接)。 我希望我可以从文章中发布样本,但我不想侵犯版权; 然而,这里是一个项目,build立一个辅助库 ,具有所有必要的function和文档 (只是忽略你不需要的东西)。
更新:这篇文章已被在线发布在新的发布者的示例项目在这里 。
到目前为止所有答案的问题是,他们没有考虑Prashant试图达到的目标。 如果夏令时前一天他的系统用户的偏移量为+12,并且设置了第二天的提醒,那么提醒应该被触发时的偏移量将是+13。
这就是为什么你只能使用当前的偏移量来处理现在正在发生的事情。 虽然我同意其他人的观点,但是所有的时候,服务器端(除了那些只用于显示的东西)都应该用UTC来存储。
如果您使用的是Framework 2.0或更高版本,则可能需要使用DateTimeOffset结构而不是DateTime。
DateTimeOffset表示相对于UTC时间的时间点,所以在这种情况下应该更容易处理。
有2个步骤:
-
使用Javascript在客户端检测不同的时区:
var dt = new Date(); var diffInMinutes = -dt.getTimezoneOffset();
-
然后在服务器端,根据上面检测到的时区偏移量,将服务器时间转换为客户端时间的C#代码:
————————;
string queryStr = Request.QueryString["diffInMinutes"]; int diffInMinutes = 0; if (Int32.TryParse(queryStr, out diffInMinutes)) { clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes); }
基本上,所有你需要做的是将偏移量(小时+分钟)添加到用户input的本地时间。 在偏移量中添加基本上给你一个在UTC(基本上GMT)时区的DateTime。
将所有时间标准化为UTC通常是最简单的,这样您的应用程序逻辑就不必处理偏移量。
这个页面有一些很好的例子: http : //msdn.microsoft.com/en-us/library/bb546099.aspx
问题在于UTC的偏移量在一年的不同时间会有所不同 – 每个时区都有自己的规则。 (在开发会议室调度应用程序时,我学到了这一点。
看起来像这里有内置的支持: http : //msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx
还没有尝试过,但它似乎承诺正确的转换,占夏时制。
如果没有,这里是一个(昂贵的)我用过的商业工具: http : //www.worldtimeserver.com/time_zone_guide/