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

发布于 2024-07-19 00:01:35 字数 301 浏览 7 评论 0原文

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

因为这是一个提醒服务,它将在特定日期向用户发送邮件。 但问题是用户并不来自特定国家,他们来自世界各地、不同时区。 现在,当我注册时,我会询问用户时区,就像 Windows 在安装时询问我们的时区一样。

但我没有得到如果用户选择了 (+5.30) 或某个时区,那么如何在我的 asp.net 应用程序中处理这个时区。 如何根据时区工作。

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

谢谢

I am working on an "online reminder system" project (ASP.NET 2.0 (C#) / SQL Server 2005)

As this is a reminder service which will send the mail to users on a particular dates. But the problem is users are not from a specific countries, they are from all over the world and from different time zones. Now When I am registering I am asking for users time zone in the same way as windows asks our time zone at the time of installation.

But I am not getting the if the user selected (+5.30) or something timezone then how to handle this time zone in my asp.net application. How to work according to timezone.

And please suggest if there is any better way to handle timezones in this application ??

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

酒几许 2024-07-26 00:01:35

首先要确保您的数据位于哪个时区。我建议确保您存储的任何 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);

First thing is to make sure which time zone your data is in. I would recommend making sure that any DateTime that you store, is stored in UTC time (use the DateTime.ToUniversalTime() to get hold of it).

When you are to store a reminder for a user, you will need the current UTC time, add or remove the user's time zone difference, and convert that new time back to UTC; this is what you want to store in the DB.

Then, when you want to check for reminders to send, you simply need to look in the database for reminders to send out now, according to UTC time; essentially get all reminders that have a time stamp that is before DateTime.Now.ToUniversalTime().

Update with some implementation specifics:
You can get a list of time zones from the TimeZoneInfo.GetSystemTimeZones() method; you can use those to show a list of time zones for the user. If you store the Id property from the selected time zone, you can create a TimeZoneInfo class instance from it, and calculate the UTC time for a given local date/time value:

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);
゛时过境迁 2024-07-26 00:01:35

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

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

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

我在 JavaScript 的 getTimezoneOffset 函数的帮助下解决了这个问题,这是唯一的 API可以告诉服务器客户端本地时间与GMT 之间的时差。 由于这是一个客户端 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, ...);
     ...
  }
}
...
}

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

更新:该文章已由新发布者此处在线发布,并包含示例项目。

I would recommend to always use UTC (GMT) time on the server side (in code-behind, database, etc), and convert time from UTC to local time for display purposes only. This means that all time manipulations - including saving time in database, performing calculations, etc - should be be done using UTC.

The problem is: how does your code-behind know what is the time zone of the client browser? Say the user enters some date/time value (such as 12/30/2009 14:30) in the form and submits it to the server. Assuming that the user submitted local time, how does the server know how to convert this value to UTC?

The application can ask the user to specify the time zone (and save it in a persistent cookie or database), but it requires and extra effort from the user, and your app would need to implement the logic and screens for this. It would be nicer if the app could determine client's time zone automatically.

I have addressed this issue with the help of JavaScript's getTimezoneOffset function, which is the only API that can tell the server about the time difference between local time on the client and GMT. Since this is a client-side API, I did the following: on the server side check for a custom session cookie holding the time offset value, and if it's not available, reload the page (only during GET, and not POST, calls) with some JavaScript logic added to generate the time offset and save it in the cookie. From the client-side this is almost transparent (once during session I reload a page on GET). Once I have the offset in the cookie, I apply it to the time management functions depending on direction of time conversion (UTC to local time, or local time to UTC).

This may sound a bit complicated, and it is, but after I wrote helper functions, integrating this feature in the site was a matter of making a single call in Page_Load (of pages that needed time conversion), and using time conversion routines when sending and retrieving time values to and from the browser. Here is an example of how it can be used:

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, ...);
     ...
  }
}
...
}

If you need more specifics, check out the It’s About Time: Localizing Time in ASP.NET Applications article (sorry, but I do not have a direct link to the article on the publisher's site, since asp.netPRO restricts access to paid subscribers only; there are links to PDF copies, though). I wish I could post the sample from the article, but I don't want to violate the copyright; however, here is a project to build a helper library that has all necessary functionality and documentation (just ignore the stuff you do not need).

UPDATE: The article has been posted online with sample project by the new publisher here.

我恋#小黄人 2024-07-26 00:01:35

到目前为止,所有答案的问题在于,它们没有考虑到普拉尚特想要实现的目标。 如果其系统的用户在夏令时更改前一天的偏移量为+12,并设置了第二天的提醒,则应触发提醒时他的偏移量将改为+13。

这就是为什么您只能对现在正在发生的事情使用当前偏移量。 尽管我确实同意其他人的观点,即服务器端的所有时间(可能仅用于显示的时间除外)都应存储在 UTC 中。

The problem with all of the answers so far is that they do not take into account what Prashant is trying to achieve. If the user of his system on the day before daylight savings changes has an offset of +12 and sets a reminder for the next day, his offset when the reminder is supposed to be triggered will be +13 instead.

That is why you can only use current offset for something that is happening now. Although I do agree with everyone else that all times server-side (except possibly those used only for display) should be stored in UTC.

风筝在阴天搁浅。 2024-07-26 00:01:35

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

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

You may want to look at using the DateTimeOffset structure instead of the DateTime if you are on framework 2.0 or later.

The DateTimeOffset represents a point in time relative to UTC time, so it should be easier to work with in this case.

白色秋天 2024-07-26 00:01:35

有 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);
}

There are 2 steps:

  • Detect different timezone at client side using Javascript:

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • Then at server side, C# code to convert server time to client time based on detected timezone offset above:

------------------------;

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}
她说她爱他 2024-07-26 00:01:35

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

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

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

Basically, all you need to do is add the offset (hours + minutes) to the local time that the user has entered. Adding in the offset basically gives you a DateTime in the UTC (basically GMT) timezone.

It's usually easiest to standardize all your times to UTC, so that your application logic doesn't have to deal with the offsets.

This page has a few good examples: http://msdn.microsoft.com/en-us/library/bb546099.aspx

撩发小公举 2024-07-26 00:01:35

问题是,与 UTC 的偏移量在一年中的不同时间会有所不同——每个时区都有自己的规则。 (我在开发会议室安排应用程序时经历了惨痛的教训。)

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

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

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

The issue is that the offset from UTC will vary at different times of the year -- each time zone has its own rules. (I learned this the hard way when developing meeting room scheduling app.)

Looks like there is built-in support here: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

Haven't tried it myself but it seems to promise the correct conversion, accounting for daylight savings.

If not, here is a (pricey) commercial tool I have used: http://www.worldtimeserver.com/time_zone_guide/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文