将美国邮政编码映射到时区[关闭]


84

当用户使用我们的应用程序注册时,我们可以根据国家数据库验证他们的邮政编码。从此邮政编码确定对他们所在时区的良好潜在猜测的最佳方法是什么?

我们正在努力使我们明确要求他们提供的数据量最小化。如果我们最好的猜测是错误的,他们将可以稍后手动设置时区。我知道邮政编码无法帮助您确定美国境外的时区,但在那种情况下,我们还是必须手动询问,无论如何我们都主要与美国打交道。

我发现了很多邮政编码数据库,到目前为止,只有少数几个包含时区信息,但是那些不是免费的,例如this。如果绝对需要为此付费订阅服务,那将是不值得的,我们只需要明确地询问用户即可。

尽管语言并不是特别相关,因为我可能可以转换所需的东西,但我们使用的是PHP和MySQL。


2
+1有关猜测的问题
克里斯·麦考尔

Answers:


37

我刚刚找到了一个免费的zip数据库,其中包括时间偏移和DST的参与。我喜欢Erik J的回答,因为它可以帮助我选择实际时区而不是偏移量(因为您永远无法完全确定规则),但是我想我可以以此为出发点,并尝试根据偏移/ dst配置找到最佳时区匹配。我想我可以尝试设置一个简单版本的Development 4.0的答案,以检查从zip信息中得到的内容是否完整。这绝对不是我希望的那么简单,但是结合起来应该可以让我至少确定90%的用户时区。


@Doug:与GeoCoding相关的任何事情都永远不会100%正确,尤其是当您仅在ZIP级别执行操作时。不过,如果您可以90%以上的时间正确无误,则可能会给您的用户带来好处。最糟糕的是您可能要离开一个小时。
埃里克·J

3
请注意,免费的zip数据库几乎总是过时的,因为邮政服务每月都会更改该文件。另请参见semaphorecorp.com/cgi/zip5.html
joe snyder 2010年

该链接带来了一些好处,但是由于我只是用它来猜测整个区域(并允许进行更正),因此我不必太担心。除非邮政编码可以跨越多个时区,否则在这种情况下,这已经是边缘情况了,而且由于我们永远不会询问用户的地址,因此无法使用这些地址进行进一步的验证。但确实,对于我们来说,在事情上线之前实际订阅一个最新的信息可能对我们很有用。免费版至少适合测试。
Doug Kavendek 2010年

2
@joesnyder链接已损坏,您可以更新还是至少解释其中的内容?
dlsso


25

大多数州都处于一个时区(尽管有一些例外)。大多数邮政编码不会跨越州界(尽管有一些例外)。

结合这些事实,您可以快速得出每个邮编自己的时区列表。

这是每个州邮政编码范围列表,以及每个时区状态列表。

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

您正在处理的大多数非美国国家/地区可能恰好位于一个时区。您可能想看看您的N大非美国游客来自何处,并只是查找他们的时区。


1
哇,有什么例外?
Hamish Grubijan

5
@Hamish:可以在Wikipedia链接中看到的多个时区的状态(每个时区的状态)的例外。我的同事在我们讲话时正在将ZIP映射到各州,并遇到了一些跨越州界的ZIP。一个例子是42223.
埃里克J.

2
另请注意,某些州(我认为只有亚利桑那州和夏威夷州)没有遵守夏令时。
乔恩·埃里克

1
美国西北部的每个州都有一百万个邮政编码。公平的警告。
Qix-蒙尼卡(Monica)错误


12

我创建了一个开放源代码(由MIT许可)的MySQL数据库表,该表可以交叉引用邮政编码和时区,并将其上载到sourceforge.net:

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

它来自四个位置(主要的Yahoo PlaceFinder API-感谢@Chris N)

有关更多信息和说明,请参见README文件。


您仍有机会生成该代码吗?现在已经有几年了,我希望获得一个新的数据集。
比利

8

如果需要的话,您还可以通过询问浏览器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)。由于夏时制总是在夏令时进行,因此我们可以将一月的两个日期之间的时间偏移与六月的两个日期之间的时间偏移进行比较。如果偏移量不同,则我们知道该位置遵守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获取时区的问题


1
谢谢!正如乔什(Josh)在其网站上提到的那样,乔恩·尼兰德(Jon Nylander)“编写了一个更强大的解决方案。请改用他的版本。” 他的版本在这里:bitbucket.org/pellepim/jstimezonedetect
Brad Parks

6

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

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

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

它们在查询字符串上需要一个unix时间戳。从返回的响应中可以看出,timeZoneName它基于时间戳考虑了夏时制,而timeZoneId时区则是与DST无关的名称。

对于我的使用,在Python中,我只是传递timestamp=0并使用该timeZoneIdtz_infopytz获取对象,然后可以使用该值在自己的代码中本地化任何特定的日期时间。

我相信对于PHP同样,您可以在http://pecl.php.net/package/timezonedb中找到“ America / New_York”


4
请注意,Google地理编码API的许可要求您使用结果显示在地图上……
Josh 2015年

@Josh您是说我不能使用地理编码API来获取某个位置来确定该位置的时区吗?
Cruncher '18

2
在政策页面上:“您可以在Google地图上显示时区API结果,也可以在没有地图上显示。如果要在地图上显示时区API结果,则这些结果必须显示在Google地图上。禁止在不是Google地图的地图上使用时区API数据。” developers.google.com/maps/documentation/timezone/policies
tmorell

4

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

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

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


1
原始的TZip和Katlean的前叉都不错,但并非100%准确。某些邮政编码(可能在最近几年推出)没有被考虑。
bigtex777 '16

1

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

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

然后

2a)使用js解决方案(Javascript / PHP和时区对其余状态)

要么

2b)使用类似@Doug上面链接的数据库。

这样,您可以为大多数用户便宜地找到tz(准确度很高!),然后使用其他更昂贵的方法之一来获取其余州的tz。

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


1

除了道格·卡文德克回答。可以使用以下方法更接近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不能插入所有链接:(因此,请使用搜索。


1

这将下载一个yaml文件,该文件会将所有时区映射到其邮政编码的数组:

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

1
这包括太平洋时间的96941(密克罗尼西亚),太平洋时间的邮政编码包括83500,但我认为美国不存在。数据是如何创建的?
贾斯汀·布朗克



0

实际上,有一个很棒的Google API。它接受一个位置并返回该位置的时区。创建一个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"
}

应该注意的是,对于1k调用,api的价格为5美元。
FlyingZebra1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.