如何通过 UTC 偏移量确定时区? [英] How can I determine a timezone by the UTC offset?

查看:33
本文介绍了如何通过 UTC 偏移量确定时区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个时区偏移量(以分钟为单位)并且需要为其确定时区的情况.我知道所有数据都不可用(例如,可能有多个时区偏移为 -240 分钟),但最佳猜测"是可以接受的.

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.

我的第一关是这样的:

foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
    if (info.BaseUtcOffset.TotalMinutes == timezoneOffset)
    {
         // do something here if this is a valid timezone
    }
}

这种方法可行,但我需要考虑夏令时,这让我有些失望.我添加了这个可怕的 hack:

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
    }
}

这足够好",因为我可以在夏令时无效时向用户显示正确的时间,并且在 DST 期间正确率约为 70%.仍然......这对我来说是一些糟糕的代码.

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.

有没有更好的方法来做到这一点?更优雅会更好,更准确会更好.

Is there a better way to do this? More elegance would be good, and more accuracy would be better still.

更新

从技术上讲,我可以访问 Javascript 可以获得的有关日期的任何信息.我有一个页面,在该页面上放置了一个名为offset"的隐藏字段.我有一个使用 DateTime().getTimezoneOffset() 填充偏移字段的 JQuery 函数.虽然我在 DateTime 对象上看不到任何有用的东西,但也许这会为想法打开其他途径.

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.

推荐答案

简答:你不能.

夏令时使它成为不可能.例如,仅从 UTC 偏移量无法确定夏季亚利桑那州和加利福尼亚州之间或冬季亚利桑那州和新墨西哥州之间的差异(因为亚利桑那州不遵守 DST).

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).

还有不同国家何时遵守夏令时的问题.例如,美国 DST 比欧洲开始早,结束晚.

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.

可能会有一个近似的猜测(即 +/- 一个小时),但如果您使用它来向用户显示时间,您将不可避免地向其中一些人显示错误的时间.

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.

更新:从评论看来,您的主要目标是在用户的本地时区显示时间戳.如果这是您想要做的,您应该将时间作为 UTC 时间戳发送,然后使用 Javascript 在用户的浏览器上重写它.如果他们没有启用 Javascript,他们仍然会看到可用的 UTC 时间戳.这是我在 this question,我在 这个 Greasemonkey 脚本.您可能需要对其进行调整以满足您的需要.

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.

//@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;
}

这篇关于如何通过 UTC 偏移量确定时区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆