C# 如何在 ASP.NET 中使用时区?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/832986/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to work with time zones in ASP.NET?
提问by Prashant
I am working on an "online reminder system" project (ASP.NET 2.0 (C#) / SQL Server 2005)
我正在做一个“在线提醒系统”项目(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.
由于这是一项提醒服务,它将在特定日期向用户发送邮件。但问题是用户并非来自特定国家/地区,而是来自世界各地和不同时区。现在,当我注册时,我询问用户时区的方式与 Windows 在安装时询问我们的时区的方式相同。
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.
但是我没有得到如果用户选择了 (+5.30) 或某个时区,那么如何在我的 asp.net 应用程序中处理这个时区。如何根据时区工作。
And please suggest if there is any better way to handle timezones in this application ??
请建议是否有更好的方法来处理此应用程序中的时区?
Thanks
谢谢
采纳答案by Fredrik M?rk
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).
第一件事是确定您的数据所在的时区。我建议确保您存储的任何 DateTime 都以 UTC 时间存储(使用DateTime.ToUniversalTime()
来获取它)。
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.
当您要为用户存储提醒时,您将需要当前的 UTC 时间,添加或删除用户的时区差异,并将该新时间转换回 UTC;这是您要存储在数据库中的内容。
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()
.
然后,当您要检查要发送的提醒时,您只需根据 UTC 时间在数据库中查找要立即发送的提醒;基本上可以获取所有时间戳在之前的提醒DateTime.Now.ToUniversalTime()
。
Updatewith 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.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);
回答by Andy White
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.
基本上,您需要做的就是将偏移量(小时 + 分钟)添加到用户输入的本地时间。添加偏移量基本上会为您提供 UTC(基本上是 GMT)时区的 DateTime。
It's usually easiest to standardize all your times to UTC, so that your application logic doesn't have to deal with the offsets.
将所有时间标准化为 UTC 通常是最简单的,这样您的应用程序逻辑就不必处理偏移量。
This page has a few good examples: http://msdn.microsoft.com/en-us/library/bb546099.aspx
这个页面有一些很好的例子:http: //msdn.microsoft.com/en-us/library/bb546099.aspx
回答by Rune Grimstad
You may want to look at using the DateTimeOffsetstructure instead of the DateTime if you are on framework 2.0 or later.
如果您使用的是框架 2.0 或更高版本,您可能需要考虑使用DateTimeOffset结构而不是 DateTime。
The DateTimeOffset represents a point in time relative to UTC time, so it should be easier to work with in this case.
DateTimeOffset 表示相对于 UTC 时间的时间点,因此在这种情况下应该更容易使用。
回答by Alek Davis
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 purposesonly. This means that all time manipulations - including saving time in database, performing calculations, etc - should be be done using UTC.
我建议在服务器端(在代码隐藏、数据库等中)始终使用 UTC (GMT) 时间,并将时间从 UTC 转换为本地时间仅用于显示目的。这意味着所有时间操作——包括在数据库中保存时间、执行计算等——都应该使用 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?
问题是:你的代码隐藏如何知道客户端浏览器的时区是什么?假设用户在表单中输入一些日期/时间值(例如12/30/2009 14:30)并将其提交给服务器。假设用户提交的是本地时间,服务器如何知道如何将这个值转换为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.
应用程序可以要求用户指定时区(并将其保存在持久性 cookie 或数据库中),但这需要用户付出额外的努力,并且您的应用程序需要为此实现逻辑和屏幕。如果应用程序可以自动确定客户端的时区会更好。
I have addressed this issue with the help of JavaScript's getTimezoneOffsetfunction, 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).
我在 JavaScript 的getTimezoneOffset函数的帮助下解决了这个问题,这是唯一可以告诉服务器客户端本地时间和 GMT 之间时差的 API。由于这是一个客户端 API,我执行了以下操作:在服务器端检查保存时间偏移值的自定义会话 cookie,如果它不可用,则重新加载页面(仅在 GET 期间,而不是在 POST 调用期间)添加了一些 JavaScript 逻辑来生成时间偏移并将其保存在 cookie 中。从客户端这几乎是透明的(有一次在会话期间我在 GET 上重新加载了一个页面)。一旦我在 cookie 中获得了偏移量,我就会根据时间转换的方向(UTC 到本地时间,或本地时间到 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 callin 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:
这听起来可能有点复杂,确实如此,但是在我编写了辅助函数之后,在站点中集成此功能只需在 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, ...);
...
}
}
...
}
If you need more specifics, check out the It's About Time: Localizing Time in ASP.NET Applicationsarticle (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 librarythat has all necessary functionality and documentation(just ignore the stuff you do not need).
如果您需要更多详细信息,请查看时间到了:在 ASP.NET 应用程序中本地化时间文章(抱歉,我没有发布者站点上该文章的直接链接,因为 asp.netPRO 仅限制对付费订阅者的访问;不过有指向 PDF 副本的链接)。我希望我可以发布文章中的样本,但我不想侵犯版权;然而,这里有一个项目来构建一个具有所有必要功能和文档的辅助库(只需忽略您不需要的东西)。
UPDATE: The article has been posted online with sample project by the new publisher here.
更新:该文章已由新出版商在此处发布,并附有示例项目。
回答by Alek Davis
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.
到目前为止,所有答案的问题在于,它们没有考虑到 Prashant 试图实现的目标。如果他的系统用户在夏令时更改前一天的偏移量为+12,并设置了第二天的提醒,那么他应该触发提醒时的偏移量将改为+13。
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.
这就是为什么您只能对正在发生的事情使用当前偏移量的原因。尽管我同意其他所有人的观点,即所有时间服务器端(可能仅用于显示的除外)都应以 UTC 格式存储。
回答by Matt Sherman
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.)
问题是与 UTC 的偏移量在一年中的不同时间会有所不同——每个时区都有自己的规则。(我在开发会议室安排应用程序时很难学到这一点。)
Looks like there is built-in support here: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx
看起来这里有内置支持: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/
如果没有,这是我使用过的(昂贵的)商业工具:http: //www.worldtimeserver.com/time_zone_guide/
回答by Minh Nguyen
There are 2 steps:
有2个步骤:
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:
使用 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);
}