2009-08-13 183 views
17

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

我第一遍是这样的:

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对象上的任何帮助,但这也许会为思路打开其他途径。

+0

@Sailing柔道:我已经添加了一些代码给我的答案,它可以让Javascript将通用时间戳转换为本地时间戳。 – Kip 2009-08-14 14:24:32

回答

16

简答:你不行。

夏令时使其不可能。例如,无法单独根据UTC偏移量来确定夏季亚利桑那州和加利福尼亚州或冬季亚利桑那州和新墨西哥州之间的差异(因为亚利桑那州没有观察到夏令时)。

还有不同国家观察夏令时的问题。例如,在美国,DST开始时间早于欧洲,晚于欧洲。

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


更新:从评论,它看起来像你的主要目标是显示在用户的本地时区的时间戳。如果这是你想要做的,你应该把时间作为UTC时间戳发送,然后用Javascript重写在用户的浏览器上。如果他们没有启用Javascript,他们仍然会看到一个可用的UTC时间戳。这是我在this question中提出的一个函数,我在this Greasemonkey script中使用了这个函数。你可能想调整它以适应你的需求。

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

这是事实,只有一个抵消是不足以确定时区的信息。您有权访问的任何其他信息?你能问一个用户的时区吗? – 2009-08-14 06:35:59

+0

@Matt:从技术上讲,我可以访问任何Javascript可以告诉我的内容,但是如果客户端当前处于DST状态,则不会在javascript DateTime对象上看到任何内容。 – 2009-08-14 12:26:14

+0

@Matt:另外,如果我能以某种方式为自己获取信息,整个练习就是试图不打扰用户的信息。因为时区的用户是绝对的最后手段。事实上,在时区有一个*主要*准确的猜测比直接询问(在我的情况下)要好。 – 2009-08-14 12:37:00

5

只知道UTC的偏移量,由于DST,您无法确定您所在的时区。您可以考虑查看时间的一部分,以便猜测当时是否有DST生效,但政治考虑几乎不可能,因为不同的司法管辖区会改变DST的定义。

1

有一些技巧,你可以在99%的时间内正确,并关闭另一个1%。检查出jstimezonedetect为非常彻底的实施。

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

相关问题