如何在ASP.NET中使用时区?

时间:2009-05-07 05:17:40

标签: c# asp.net timezone reminders

我正在开发一个“在线提醒系统”项目(ASP.NET 2.0(C#)/ SQL Server 2005)

因为这是一个提醒服务,它会在特定日期将邮件发送给用户。但问题是用户不是来自特定国家,而是来自世界各地和不同时区。现在当我注册时,我要求用户时区的方式与Windows在安装时询问我们的时区一样。

但我没有得到用户选择(+5.30)或时区如何在我的asp.net应用程序中处理这个时区。如何按时区工作。

请建议是否有更好的方法来处理此应用程序中的时区??

由于

7 个答案:

答案 0 :(得分:27)

首先要确保您的数据所在的时区。我建议确保您存储的任何DateTime都以UTC时间存储(使用DateTime.ToUniversalTime()来获取它)。< / p>

当您要为用户存储提醒时,您将需要当前的UTC时间,添加或删除用户的时区差异,并将该新时间转换回UTC;这就是您要存储在数据库中的内容。

然后,当您想要检查要发送的提醒时,您只需根据UTC时间在数据库中查找现在发送的提醒;基本上得到所有提醒的时间戳都在DateTime.Now.ToUniversalTime()之前。

更新以及一些实施细节: 您可以从TimeZoneInfo.GetSystemTimeZones()方法获取时区列表;您可以使用它们显示用户的时区列表。如果存储所选时区的Id属性,则可以从中创建TimeZoneInfo类实例,并计算给定本地日期/时间值的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);

答案 1 :(得分:17)

我建议始终在服务器端使用UTC(GMT)时间(在代码隐藏,数据库等),并将时间从UTC转换为本地时间以便显示仅限。这意味着所有时间操作 - 包括在数据库中节省时间,执行计算等 - 都应该使用UTC来完成。

问题是:您的代码隐藏如何知道客户端浏览器的时区是什么?假设用户在表单中输入了一些日期/时间值(例如 12/30/2009 14:30 )并将其提交给服务器。假设用户提交了本地时间,服务器如何知道如何将此值转换为UTC?

应用程序可以要求用户指定时区(并将其保存在持久性cookie或数据库中),但这需要用户付出额外的努力,并且您的应用程序需要为此实现逻辑和屏幕。如果应用可以自动确定客户的时区,那就更好了。

我在JavaScript的getTimezoneOffset函数的帮助下解决了这个问题,这是唯一能告诉服务器客户端本地时间与GMT之间时差的API。由于这是一个客户端API,我做了以下操作:在服务器端检查保存时间偏移值的自定义会话cookie,如果它不可用,重新加载页面(仅在GET期间,而不是POST,调用)添加一些JavaScript逻辑以生成时间偏移并将其保存在cookie中。从客户端来看,这几乎是透明的(在会话期间我在GET上重新加载页面)。一旦我在cookie中有偏移量,我就会根据时间转换的方向(UTC到当地时间,或当地时间到UTC)将它应用到时间管理功能。

这可能听起来有点复杂,但是在我编写帮助函数之后,在网站中集成此功能是在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, ...);
     ...
  }
}
...
}

如果您需要更多细节,请查看It’s About Time: Localizing Time in ASP.NET Applications文章(抱歉,但我没有指向发布商网站上文章的直接链接,因为asp.netPRO仅限制对付费订阅者的访问权限;但是,链接到PDF副本。我希望我可以发表文章中的样本,但我不想侵犯版权;但是,这里有project to build a helper library 所有必要的功能和文档(只是忽略了你不需要的东西)。

更新:该文章已由新发布商here在线发布了示例项目。

答案 2 :(得分:3)

到目前为止,所有答案的问题在于它们没有考虑到Prashant试图实现的目标。如果他的系统用户在夏令时变化前一天的偏移量为+12并设置了第二天的提醒,那么当应该触发提醒时他的偏移量将是+13。

这就是为什么你只能使用当前偏移来解决现在正在发生的事情。虽然我同意其他所有人都认为服务器端(除了可能仅用于显示的那些)应该以UTC格式存储。

答案 3 :(得分:2)

如果您使用的是框架2.0或更高版本,则可能需要使用DateTimeOffset结构而不是DateTime。

DateTimeOffset表示相对于UTC时间的时间点,因此在这种情况下应该更容易使用。

答案 4 :(得分:1)

有两个步骤:

  • 使用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);
}

答案 5 :(得分:0)

基本上,您需要做的就是将偏移量(小时+分钟)添加到用户输入的本地时间。添加偏移量基本上为您提供UTC(基本上是GMT)时区的DateTime。

将所有时间标准化为UTC通常最简单,这样您的应用程序逻辑就不必处理偏移量。

此页面有一些很好的例子:http://msdn.microsoft.com/en-us/library/bb546099.aspx

答案 6 :(得分:0)

问题在于,UTC的偏移量会在一年中的不同时间发生变化 - 每个时区都有自己的规则。 (在开发会议室调度应用程序时,我学到了很多东西。)

看起来这里有内置支持:http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

我自己没有尝试过,但它似乎承诺正确的转换,考虑到夏令时。

如果没有,这是我使用的(昂贵的)商业工具:http://www.worldtimeserver.com/time_zone_guide/