C# 如何通过 UTC 偏移量确定时区?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1274743/
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 can I determine a timezone by the UTC offset?
提问by Sailing Judo
I have a scenario where I have a timezone offset (in minutes) and need to determine the timezone for it. I know that all the data is not available (for example, there may be several timezones with an offset of -240 minutes) but a "best guess" is acceptable.
我有一个场景,我有一个时区偏移量(以分钟为单位),需要确定它的时区。我知道所有数据都不可用(例如,可能有几个时区的偏移量为 -240 分钟),但“最佳猜测”是可以接受的。
My first pass looked like this:
我的第一遍看起来是这样的:
foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
if (info.BaseUtcOffset.TotalMinutes == timezoneOffset)
{
// do something here if this is a valid timezone
}
}
This sorta works, but I need to account for daylight savings which is throwing me off somewhat. I added this terrible hack:
这有点工作,但我需要考虑夏令时这有点让我失望。我添加了这个可怕的黑客:
foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
var extra = info.IsDaylightSavingTime(DateTime.Now) ? 60 : 0;
if (info.BaseUtcOffset.TotalMinutes + extra == timezoneOffset)
{
// do something here if this is a valid timezone
}
}
This works "well enough" in that I can show the user the correct time for them when daylight savings is not in effect and am about 70% correct during DST. Still... this is some awful code to my eyeballs.
这“足够好”,因为我可以在夏令时无效时向用户显示正确的时间,并且在 DST 期间正确率约为 70%。仍然......这对我的眼球来说是一些糟糕的代码。
Is there a better way to do this? More elegance would be good, and more accuracy would be better still.
有一个更好的方法吗?更优雅会更好,更准确会更好。
Update
更新
Technically I have access to any information Javascript can get regarding the date. I have a page on which I've placed a hidden field called "offset". I have a JQuery function that populates the offset field with the DateTime().getTimezoneOffset(). While I don't see anything on the DateTime object that will help, perhaps this will open other avenues for ideas.
从技术上讲,我可以访问 Javascript 可以获得的有关日期的任何信息。我有一个页面,我在其中放置了一个名为“偏移量”的隐藏字段。我有一个 JQuery 函数,它用 DateTime().getTimezoneOffset() 填充偏移字段。虽然我在 DateTime 对象上没有看到任何有用的东西,但也许这会为想法开辟其他途径。
采纳答案by Kip
Short answer: you can't.
简短的回答:你不能。
Daylight saving time make it impossible. For example, there is no way to determine, solely from UTC offset, the difference between Arizona and California in the summer, or Arizona and New Mexico in the winter (since Arizona does not observe DST).
夏令时使之成为不可能。例如,无法仅根据 UTC 偏移量确定夏季亚利桑那州和加利福尼亚州之间或冬季亚利桑那州和新墨西哥州之间的差异(因为亚利桑那州不遵守夏令时)。
There is also the issue of what time different countries observe DST. For example, in the US DST starts earlier and ends later than in Europe.
还有一个问题是不同国家在什么时候观察夏令时。例如,在美国,DST 比欧洲的夏令时开始早,结束晚。
A close guess is possible (i.e. +/- an hour), but if you are using it to display time to users you will inevitably display the wrong time to some of them.
一个近似的猜测是可能的(即 +/- 一个小时),但是如果您使用它向用户显示时间,您将不可避免地向其中一些人显示错误的时间。
Update: From the comments, it looks like your primary goal is to display a timestamp in the user's local timezone. If that is what you want to do, you should send the time as a UTC timestamp, and then just rewrite it on the user's browser with Javascript. In the case that they don't have Javascript enabled, they would still see a usable UTC timestamp. Here is a function I came up with in this question, which I used in this Greasemonkey script. You may want to tweak it to suit your needs.
更新:从评论来看,您的主要目标似乎是在用户的本地时区显示时间戳。如果这是您想要做的,您应该将时间作为 UTC 时间戳发送,然后使用 Javascript 在用户的浏览器上重写它。如果他们没有启用 Javascript,他们仍然会看到可用的 UTC 时间戳。这是我在这个问题中提出的一个函数,我在这个 Greasemonkey 脚本中使用了它。您可能想要调整它以满足您的需求。
//@param timestamp An ISO-8601 timestamp in the form YYYY-MM-DDTHH:MM:SS±HH:MM
//Note: Some other valid ISO-8601 timestamps are not accepted by this function
function parseISO8601(timestamp)
{
var regex = new RegExp("^([\d]{4})-([\d]{2})-([\d]{2})T([\d]{2}):([\d]{2}):([\d]{2})([\+\-])([\d]{2}):([\d]{2})$");
var matches = regex.exec(timestamp);
if(matches != null)
{
var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
if(matches[7] == "-")
offset = -offset;
return new Date(
Date.UTC(
parseInt(matches[1], 10),
parseInt(matches[2], 10) - 1,
parseInt(matches[3], 10),
parseInt(matches[4], 10),
parseInt(matches[5], 10),
parseInt(matches[6], 10)
) - offset*60*1000
);
}
return null;
}
Here is a function I use on my blog to display a parsed timestamp in the user's local timezone. Again, you can tweak it to the format you want.
这是我在博客上使用的一个函数,用于在用户的本地时区显示解析的时间戳。同样,您可以将其调整为您想要的格式。
var weekDays = new Array("Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday");
var months = new Array("January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December");
function toLocalTime(date)
{
var hour = date.getHours();
var ampm = (hour < 12 ? "am" : "pm");
hour = (hour + 11)%12 + 1;
var minutes = date.getMinutes();
if(minutes < 10)
minutes = "0" + minutes;
return weekDays[date.getDay()] + ", "
+ months[date.getMonth()] + " "
+ date.getDate() + ", "
+ date.getFullYear() + " at "
+ hour + ":"
+ minutes + " "
+ ampm;
}
回答by Ned Batchelder
Knowing just the offset from UTC, you can't tell what timezone you are in, because of DST. You could consider looking at the time part of the time to try to guess whether DST was in effect then or not, but political considerations make that nearly impossible, as different jurisdictions change the definition of DST.
由于 DST,仅知道与 UTC 的偏移量,您无法判断您所在的时区。您可以考虑在一段时间内查看时间以尝试猜测 DST 那时是否有效,但考虑使这几乎不可能,因为不同的司法管辖区会更改 DST 的定义。