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

Pra*_*ant 27 c# asp.net timezone reminders

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

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

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

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

谢谢

Fre*_*örk 27

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

当您要为用户存储提醒时,您将需要当前的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);
Run Code Online (Sandbox Code Playgroud)

  • @Prashant:很抱歉没有回复你:答案是BaseUtcOffset应该*总是从当地时间减去,因为它已签名; 在UTC之前的时区(例如IST)中,BaseTimeOffset返回具有正值的TimeSpan,但对于UTC之后的时区(例如美国东部标准时间),它返回负时间跨度; 所以如果UTC是12:00并且你有一个-1小时偏移的时区(所以当地时间是11:00)你会得到11:00 - ( - 1)小时=> 11:00 + 1小时=> 12:00. (3认同)
  • @Matt - 这篇文章可能很旧,但这是非常错误的.您不应手动减去基本偏移量.您应该使用[`TimeZoneInfo.ConvertTime`](http://msdn.microsoft.com/en-us/library/bb382770.aspx)从用户的时间转到UTC.如果您只想知道任意时间的偏移量,可以使用[`GetUtcOffset`](http://msdn.microsoft.com/en-us/library/bb396378.aspx).另请注意,当询问此问题时,`Time 2.0中没有`TimeZoneInfo`.最后 - 你真的应该在一个新问题中提出这类问题而不是对一篇5年前的帖子发表评论. (3认同)

Ale*_*vis 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, ...);
     ...
  }
}
...
}
Run Code Online (Sandbox Code Playgroud)

如果您需要更多细节,请查看它是关于时间:在ASP.NET应用程序中本地化时间文章(对不起,但我没有直接链接到发布者网站上的文章,因为asp.netPRO仅限制对付费订阅者的访问;但是有PDF副本的链接.我希望我可以发表文章中的样本,但我不想侵犯版权; 但是,这是一个构建帮助程序库项目,该库具有所有必要的功能和文档(只需忽略您不需要的东西).

UPDATE:文章已经在线与示例项目由新发布者发布在这里.

  • 我不明白你的观点布鲁诺.首先,没有与时区关联的业务规则.这是一个可用性问题.我们可以使用GMT,但对用户来说不方便,所以我们使用当地时间.如果用户更改系统时钟(或用于指定时区的任何方式),谁在乎?我这里没有看到问题.我也没有遵循从你的第一个陈述到第二个陈述的过渡.你不喜欢"自动"部分,或者你不喜欢使用本地时间的想法(如果没有自动完成,用户必须能够以某种方式改变它,对吧)? (4认同)