C# 将我的 DateTime 转换为 UTC 时遇到问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1354516/
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
Having problems with converting my DateTime to UTC
提问by chobo2
I am storing all my dates in UTC format in my database. I ask the user for their timezone and I want to use their time zone plus what I am guessing is the server time to figure out the UTC for them.
我将所有日期以 UTC 格式存储在我的数据库中。我向用户询问他们的时区,我想使用他们的时区加上我猜测的服务器时间来为他们找出 UTC。
Once I have that I want to do a search to see what is range in the database using their newly converted UTC date.
一旦我有了它,我想使用他们新转换的 UTC 日期进行搜索以查看数据库中的范围。
but I always get this exception.
但我总是得到这个例外。
System.ArgumentException was unhandled by user code
Message="The conversion could not be completed because the
supplied DateTime did not have the Kind property set correctly.
For example, when the Kind property is DateTimeKind.Local,
the source time zone must be TimeZoneInfo.Local.
Parameter name: sourceTimeZone"
I don't know why I am getting this.
我不知道为什么我会得到这个。
I tried 2 ways
我尝试了 2 种方法
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(id);
// I also tried DateTime.UtcNow
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone );
This failed so I tired
这失败了所以我累了
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now,
ZoneId, TimeZoneInfo.Utc.Id);
This also failed both with the same error. What am I doing wrong?
这也因相同的错误而失败。我究竟做错了什么?
Edit would this work?
编辑这行得通吗?
DateTime localServerTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(id);
var usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);
var utc = TimeZoneInfo.ConvertTimeToUtc(usersTime, userInfo);
Edit 2 @ Jon Skeet
编辑 2 @ Jon Skeet
Ya I was just thinking about that I might not even need to do all this. Time stuff confuses me right now so thats why the post may not be as clear as it should be. I never know what the heck DateTime.Now is getting (I tried to change my Timezone to another timezone and it kept getting my local time).
是的,我只是在想我可能甚至不需要做这一切。时间的东西现在让我感到困惑,所以这就是为什么帖子可能不像它应该的那样清晰。我永远不知道 DateTime.Now 到底得到了什么(我试图将我的时区更改为另一个时区,但它一直在获取我的本地时间)。
This is what I wanted my stuff to do. User comes to site adds some alert and it gets now saved as utc (before it was DateTime.Now then someone suggested to store everything UTC).
这就是我想让我的东西做的事情。用户来到站点添加一些警报,它现在被保存为 utc(在它之前是 DateTime.Now 然后有人建议存储所有 UTC)。
So before a user would come to my site and depending where my hosting server was it could be like on the next day. So if the alert was said to be shown on August 30th (their time) but with the time difference of the server they could come on August 29th and the alert would be shown.
因此,在用户访问我的网站之前,根据我的托管服务器的位置,它可能会在第二天出现。因此,如果说警报在 8 月 30 日(他们的时间)显示,但由于服务器的时差,他们可能会在 8 月 29 日出现,并且警报将被显示。
So I wanted to combat that. So now I am not sure should I just store their local time then use this offset stuff? Or just store UTC time. With just storing UTC time still might be wrong since the user still probably would be thinking in local time and I am not sure how UTC really works it still could end up a difference of time.
所以我想与它作斗争。所以现在我不确定我是否应该只存储他们的当地时间然后使用这个偏移量?或者只是存储UTC时间。仅存储 UTC 时间仍然可能是错误的,因为用户仍然可能会考虑本地时间,而且我不确定 UTC 是如何真正工作的,它仍然可能导致时间差异。
Edit3
编辑3
var info = TimeZoneInfo.FindSystemTimeZoneById(id)
DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(DataBaseUTCDate,
TimeZoneInfo.Utc, info);
采纳答案by dtb
The DateTime
structure supports only two timezones:
该DateTime
结构仅支持两个时区:
- The localtimezone the machine is running in.
- and UTC.
- 机器运行所在的本地时区。
- 和 UTC。
Have a look at the DateTimeOffsetstructure.
看看DateTimeOffset结构。
var info = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);
DateTimeOffset utc = localServerTime.ToUniversalTime();
Console.WriteLine("Local Time: {0}", localServerTime);
Console.WriteLine("User's Time: {0}", usersTime);
Console.WriteLine("UTC: {0}", utc);
Output:
输出:
Local Time: 30.08.2009 20:48:17 +02:00
User's Time: 31.08.2009 03:48:17 +09:00
UTC: 30.08.2009 18:48:17 +00:00
回答by SLaks
You need to set the Kind
to Unspecified
, like this:
您需要将 设置Kind
为Unspecified
,如下所示:
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone);
DateTimeKind.Local
means the in local time zone, and not any other time zone. That's why you were getting the error.
DateTimeKind.Local
表示本地时区,而不是任何其他时区。这就是你收到错误的原因。
回答by Jon Skeet
As dtb says, you should use DateTimeOffset
if you want to store a date/time with a specific time zone.
正如 dtb 所说,DateTimeOffset
如果要存储具有特定时区的日期/时间,则应该使用。
However, it's not at all clear from your post that you really need to. You only give examples using DateTime.Now
and you say you're guessingthat you're using the server time. What time do you actually want? If you just want the current time in UTC, use DateTime.UtcNow
or DateTimeOffset.UtcNow
. You don't need to know the time zone to know the current UTC time, precisely because it's universal.
但是,从您的帖子中并不清楚您确实需要这样做。你只给出了使用的例子DateTime.Now
,你说你在猜测你正在使用服务器时间。你真正想要什么时间?如果您只想要 UTC 中的当前时间,请使用DateTime.UtcNow
或DateTimeOffset.UtcNow
。您无需知道时区即可知道当前的 UTC 时间,正是因为它是通用的。
If you're getting a date/time from the user in some other way, please give more information - that way we'll be able to work out what you need to do. Otherwise we're just guessing.
如果您以其他方式从用户那里获得日期/时间,请提供更多信息 - 这样我们就可以确定您需要做什么。否则我们只是猜测。
回答by SLaks
UTCis just a time zone that everyone agreed on as the standard time zone. Specifically, it's a time zone that contains London, England. EDIT: Note that it's not the exact same time zone; for example, UTC has no DST. (Thanks, Jon Skeet)
UTC只是每个人都同意作为标准时区的时区。具体来说,它是一个包含英国伦敦的时区。 编辑:请注意,它不是完全相同的时区;例如,UTC 没有 DST。(谢谢,乔恩斯基特)
The only special thing about UTC is that it's much easier to use in .Net than any other time zone (DateTime.UtcNow
, DateTime.ToUniversalTime
, and other members).
关于UTC唯一特别的是,它更容易在.net中使用比任何其它时区(DateTime.UtcNow
,DateTime.ToUniversalTime
,和其他成员)。
Therefore, as others have mentioned, the best thing for you to do is store all dates in UTC within your database, then convert to the user's local time (by writing TimeZoneInfo.ConvertTime(time, usersTimeZone)
before displaying.
因此,正如其他人所提到的,您最好的做法是将所有日期以 UTC 格式存储在您的数据库中,然后转换为用户的本地时间(通过TimeZoneInfo.ConvertTime(time, usersTimeZone)
在显示之前写入。
If you want to be fancier, you can geolocateyour users' IP addresses to automatically guess their time zones.
如果您想变得更有趣,您可以对用户的 IP 地址进行地理定位以自动猜测他们的时区。
回答by JohnOpincar
Everyone else's answer seems overly complex. I had a specific requirement and this worked fine for me:
其他人的答案似乎过于复杂。我有一个特定的要求,这对我来说很好用:
void Main()
{
var startDate = DateTime.Today;
var StartDateUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.SpecifyKind(startDate.Date, DateTimeKind.Unspecified), "Eastern Standard Time", "UTC");
startDate.Dump();
StartDateUtc.Dump();
}
Which outputs (from linqpad) what I expected:
哪些输出(来自 linqpad)是我所期望的:
12/20/2013 12:00:00 AM
12/20/2013 12:00:00 上午
12/20/2013 5:00:00 AM
2013/12/20 上午 5:00:00
Props to Slaks for the Unspecified kind tip. That's what I was missing. But all the talk about there being only two kinds of dates (local and UTC) just muddled the issue for me.
为 Slaks 提供未指定种类提示的道具。这就是我所缺少的。但是所有关于只有两种日期(本地和 UTC)的讨论都让我感到困惑。
FYI -- the machine I ran this on was in Central Time Zone and DST was not in effect.
仅供参考 - 我运行它的机器在中央时区并且 DST 无效。