C# 如何通过UTC偏移量确定时区?

C# 如何通过UTC偏移量确定时区?,c#,javascript,timezone,utc,C#,Javascript,Timezone,Utc,我有一个场景,其中我有一个时区偏移量(以分钟为单位),需要确定它的时区。我知道所有数据都不可用(例如,可能有几个时区的偏移量为-240分钟),但“最佳猜测”是可以接受的 我的第一次传球是这样的: foreach (var info in TimeZoneInfo.GetSystemTimeZones()) { if (info.BaseUtcOffset.TotalMinutes == timezoneOffset) { // do something here

我有一个场景,其中我有一个时区偏移量(以分钟为单位),需要确定它的时区。我知道所有数据都不可用(例如,可能有几个时区的偏移量为-240分钟),但“最佳猜测”是可以接受的

我的第一次传球是这样的:

foreach (var info in TimeZoneInfo.GetSystemTimeZones())
{
    if (info.BaseUtcOffset.TotalMinutes == timezoneOffset)
    {
         // do something here if this is a valid timezone
    }
}
这类方法是有效的,但我需要考虑一下夏令时,这让我有些不舒服。我添加了一个可怕的黑客:

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%正确。还是。。。对我来说,这是一些糟糕的代码

有更好的方法吗?越优雅越好,越准确越好

更新


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

简短回答:你不能

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

还有一个问题是,不同国家何时遵守DST。例如,在美国,DST比在欧洲开始得早,结束得晚

精确猜测是可能的(即+/-1小时),但如果您使用它向用户显示时间,则不可避免地会向其中一些用户显示错误的时间


更新:从评论来看,您的主要目标似乎是在用户的本地时区中显示时间戳。如果这是您想要做的,您应该将时间作为UTC时间戳发送,然后使用Javascript在用户浏览器上重写它。在没有启用Javascript的情况下,他们仍然可以看到可用的UTC时间戳。这是我在中提出的一个函数,我在中使用了它。您可能需要调整它以满足您的需要

//@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;
}
下面是我在博客上使用的一个函数,用于在用户的本地时区中显示解析的时间戳。同样,您可以将其调整为所需的格式

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;
}
var weekDays=新数组(“星期日”、“星期一”、“星期二”、“星期三”,
“星期四”、“星期五”、“星期六”);
var months=新数组(“一月”、“二月”、“三月”、“四月”、“五月”、“六月”,
“七月”、“八月”、“九月”、“十月”、“十一月”、“十二月”);
函数到本地时间(日期)
{
var hour=date.getHours();
var ampm=(小时<12?:上午:“下午”);
小时=(小时+11)%12+1;
var minutes=date.getMinutes();
如果(分钟<10)
分钟=“0”+分钟;
返回工作日[date.getDay()]+“,”
+月[date.getMonth()]+“”
+date.getDate()+“,”
+date.getFullYear()+“在”
+小时+“:”
+分钟+“”
+ampm;
}

只知道UTC的偏移量,由于DST的原因,您无法分辨您所在的时区。你可以考虑时间的一部分来猜测DST是否生效,但是政治考虑使得几乎不可能,因为不同的司法管辖区改变了DST的定义。

这是真的,单靠一个偏移量是不足以确定时区的信息。您有权访问其他信息吗?你可以向用户询问时区吗?@Matt:从技术上讲,我可以访问Javascript可以告诉我的任何内容,但我在Javascript DateTime对象上看不到任何内容,如果客户端当前是否在DST中,该对象将返回。@Matt:此外,如果我能自己获取信息,整个练习就是为了不打扰用户。作为用户,时区是绝对的最后手段。事实上,对时区有一个大致准确的猜测比直接问(就我而言)要好。@帆船柔道:当然,也有缺点。既然是客户报告的,他仍然可以在字符串中放入任何他想要的内容。他的机器可能不知道正确的时间。而且,正如我所介绍的,那实际上是他加载页面的时间,而不是他发表文章的时间。你可以让Javascript每30秒更新一次隐藏字段,这样你的时间戳就不会超过30秒。如果我们假设没有DST呢?DST毕竟会影响+-1小时。@Sailing Judo:我在我的答案中添加了一些代码,让Javascript将通用时间戳转换为本地时间戳。