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

我有一个场景,我有一个时区偏移(以分钟为单位),需要确定它的时区。 我知道所有数据都不可用(例如,可能有几个时区的偏移量为-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 } } 

这样做“足够好”,因为当夏令时没有生效时,我可以向用户显示正确的时间,并且在夏令时期间大约70%是正确的。 仍然……这对我的眼球来说是一些可怕的代码。

有一个更好的方法吗? 更优雅会更好,更准确更好。

更新

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

简答:你不能。

夏令时使其无法实现。 例如,无法仅根据UTC偏移量确定夏季亚利桑那州和加利福尼亚州之间的差异,或冬季亚利桑那州和新墨西哥州之间的差异(因为亚利桑那州不遵守DST)。

还有一个问题是不同国家什么时候观察夏令时。 例如,在美国,DST早于欧洲开始,结束时间晚于欧洲。

可以进行近距离猜测(即+/-一小时),但如果您使用它来向用户显示时间,您将不可避免地向其中一些人显示错误的时间。


更新 :从评论中看,您的主要目标是在用户的本地时区显示时间戳。 如果这是您想要做的,您应该将时间作为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; } 

这是我在博客上使用的一个函数,用于在用户的本地时区显示已解析的时间戳。 同样,您可以将其调整为您想要的格式。

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

由于DST,您只知道与UTC的偏差,无法确定您所处的时区。 您可以考虑在时间部分时间尝试猜测DST是否有效,但政治因素几乎不可能,因为不同的司法管辖区会改变DST的定义。

通过一些技巧,你可以99%的时间正确,并关闭另一个1%。 查看jstimezonedetect以获得极其全面的实施。

穷人的方法是手动将每个可能报告的时区偏移量映射到您的最佳猜测。 既然你猜测你也可能是明确的!