将美国邮政编码映射到时区

当用户注册我们的应用程序,我们能够推断他们的邮政编码,当我们validation他们对国家数据库。 从这个邮政编码中确定一个很好的时区猜测的最好方法是什么?

我们正在尽量减less我们明确要求他们提供的数据量。 如果我们最好的猜测是错误的,他们将能够手动设置时区。 我意识到邮政编码无助于搞清楚美国以外的时区,但在这种情况下,我们不得不手动提出问题,而且我们主要与美国打交道。

我发现了许多邮政编码数据库,到目前为止只有less数几个包含时区信息,但是那些做的并不是免费的,比如这个 。 如果为了做到这一点而支付订购服务是绝对必要的,那么这将是不值得的,我们只需要明确地询问用户。

虽然语言不是特别相关,因为我可以转换东西,但我们正在使用PHP和MySQL。

我刚刚find一个包含时间偏移和参与DST的免费zip数据库 。 我喜欢Erik J的回答,因为它会帮助我select实际的时区,而不仅仅是抵消(因为你永远无法完全确定规则),但是我想我可以从这个开始,尝试根据偏移/ dstconfigurationfind最佳时区匹配。 我想我可能会尝试设置一个简单版本的开发4.0的答案来检查我从zip信息中得到的是一个完整性testing。 这绝对不是我希望的那么简单,但是一个组合应该使我至less有90%的用户时区确定。

大多数州只有一个时区(尽pipe有一些例外)。 大多数邮政编码不跨越国界(尽pipe有一些例外)。

通过结合这些事实,您可以快速提出自己的每个时区的时区列表。

以下是每个州的邮政编码范围列表,以及每个时区的州名单。

您可以查看邮政编码的边界,并使用此链接或Google地球与时区地图进行比较,以便将时区与时区线分开的州的时区映射到时区。

你所处理的大部分非美国国家可能都在一个时区。 你可能想看看你的前N非美国访客来自哪里,只是查找他们的时区。

我创build了一个开源(MIT许可)的MySQL数据库表,它将邮政编码和时区交叉引用并将其上传到sourceforge.net:

http://sourceforge.net/projects/zip2timezone/files/

它来源于四个位置(主雅虎PlaceFinder API – 谢谢@Chris N)

请参阅自述文件以获取更多信息和说明。

如果你愿意,你也可以通过问浏览器Josh Fraser 在这里写一个好的文章来感受一下时区

var rightNow = new Date(); var jan1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0); var temp = jan1.toGMTString(); var jan2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var std_time_offset = (jan1 - jan2) / (1000 * 60 * 60); 

您需要知道的第二件事是该位置是否遵守夏令时(DST)。 由于夏季总是会观测到夏令时,所以我们可以比较一月份两个date之间的时间偏差,以及六月份两个date之间的时间偏差。 如果偏移量不同,那么我们知道该位置观察DST。 如果偏移量相同,则我们知道该位置不会观察到DST。

 var june1 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0); temp = june1.toGMTString(); var june2 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1)); var daylight_time_offset = (june1 - june2) / (1000 * 60 * 60); var dst; if (std_time_offset == daylight_time_offset) { dst = "0"; // daylight savings time is NOT observed } else { dst = "1"; // daylight savings time is observed } 

所有这一切都归功于乔什·弗雷泽(Josh Fraser)。

这可能会帮助您与美国以外的客户,这可能会补充您的压缩方法。

这里有一个关于从javascript获取时区的问题

Google为此提供了一个特定的API: https : //developers.google.com/maps/documentation/timezone/

例如: https : //maps.googleapis.com/maps/api/timezone/json?location=40.704822,-74.0137431&timestamp=0

 { dstOffset: 0, rawOffset: -18000, status: "OK", timeZoneId: "America/New_York", timeZoneName: "Eastern Standard Time" } 

它们需要查询string上的unix时间戳。 根据返回的响应, timeZoneName会根据时间戳记考虑夏令时,而timeZoneId是时区的与DST无关的名称。

对于我的使用,在Python中,我只是通过timestamp=0并使用timeZoneId值从pytz获得tz_info对象,然后我可以使用它来本地化我自己的代码中的任何特定的date时间。

我相信对于PHP类似的,你可以在http://pecl.php.net/package/timezonedbfind“America / New_York”

Ruby gem将邮政编码转换为时区: https : //github.com/Katlean/TZip (从https://github.com/farski/TZip分叉)。;

 > ActiveSupport::TimeZone.find_by_zipcode('90029') => "Pacific Time (US & Canada)" 

它的速度很快,很小,并且没有外部依赖性,但请记住,邮政编码只是不能完美映射到时区。

我一直在为自己的网站研究这个问题,觉得我已经提出了一个很好的解决scheme

1)将时区分配给只有一个时区的所有状态(大多数状态)

然后也是

2a)为剩下的状态使用js解决scheme( Javascript / PHP和时区 )

要么

2b)使用像上面通过@Doug链接的数据库。

这样,你可以为你的大多数用户便宜地findtz(并且非常准确!),然后使用其他更昂贵的方法之一来获得其他州的tz。

不是超级优雅,但对我来说比对每个用户使用js或数据库似乎更好。

另外请注意,如果您碰巧使用的是Yahoo地理编码服务,则可以通过设置正确的标志将时区信息返回给您。

http://developer.yahoo.com/geo/placefinder/guide/requests.html#flags-parameter

除了Doug Kavendek的回答。 可以使用下面的方法来更接近tz_database。

  1. 下载[免费邮编经纬度数据库]
  2. 下载[世界TZ时区的shapefile]
  3. 使用任何免费的库来查询shapefile(例如.NET Easy GIS .NET ,LGPL)。
     var shapeFile = new ShapeFile(shapeFilePath);
     var shapeIndex = shapeFile.GetShapeIndexContainingPoint(new PointD(long,lat),0D);
     var attrValues = shapeFile.GetAttributeFieldValues(shapeIndex);
     var timeZoneId = attrValues [0];

PS不能插入所有的链接:(所以请使用search。

实际上有一个很棒的Google API。 它需要一个位置并返回该位置的时区。 应该很简单,创build一个bash或python脚本来获取CSV文件或数据库中每个地址的结果,然后保存时区信息。

https://developers.google.com/maps/documentation/timezone/start

请求端点:

 https://maps.googleapis.com/maps/api/timezone/json?location=38.908133,-77.047119&timestamp=1458000000&key=YOUR_API_KEY 

响应:

 { "dstOffset" : 3600, "rawOffset" : -18000, "status" : "OK", "timeZoneId" : "America/New_York", "timeZoneName" : "Eastern Daylight Time" } 

我最近做了一个美国所有邮编的Ruby散列,以及如果你感兴趣的话,你可以使用它们相关的时区 。 应该很容易为您的目的进行逆向工程。

这将下载一个yaml文件,将所有的时区映射到他们的zipcode的数组:

 curl https://gist.githubusercontent.com/anonymous/01bf19b21da3424f6418/raw/0d69a384f55c6f68244ddaa07e0c2272b44cb1de/timezones_to_zipcodes.yml > timezones_to_zipcodes.yml 

例如

 "Eastern Time (US & Canada)" => ["00100", "00101", "00102", "00103", "00104", ...] "Central Time (US & Canada)" => ["35000", "35001", "35002", "35003", "35004", ...] etc... 

如果你喜欢缩短的时区,你可以运行这个:

 curl https://gist.githubusercontent.com/anonymous/4e04970131ca82945080/raw/e85876daf39a823e54d17a79258b170d0a33dac0/timezones_to_zipcodes_short.yml > timezones_to_zipcodes.yml 

例如

 "EDT" => ["00100", "00101", "00102", "00103", "00104", ...] "CDT" => ["35000", "35001", "35002", "35003", "35004", ...] etc...