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

时间:2010-03-16 16:46:40

标签: timezone zipcode

当用户注册我们的应用时,我们可以在我们根据国家数据库验证邮政编码时推断他们的邮政编码。从这个邮政编码确定他们的时区的潜在猜测的最佳方法是什么?

我们正在努力减少我们明确要求他们提供的数据量。如果我们的最佳猜测是错误的,他们将能够稍后手动设置时区。我意识到邮政编码无助于找出美国以外的时区,但在这种情况下,无论如何我们都必须手动询问,而且无论如何我们主要与美国打交道。

我发现了很多邮政编码数据库,到目前为止只有少数包含时区信息,但那些不是免费的,例如this one。如果为了做到这一点而支付订阅服务是绝对必要的,那么它就不值得了,我们只需要明确询问用户。

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

14 个答案:

答案 0 :(得分:37)

我刚刚找到一个free zip database,其中包括时间偏移和参与夏令时。我喜欢Erik J的答案,因为它可以帮助我选择实际的时区而不是偏移(因为你永远不能完全确定规则),但我想我可能会从这开始,并尝试根据偏移/ dst配置找到最佳时区匹配。我想我可能会尝试设置一个简单版本的Development 4.0的答案来检查我从zip信息中得到的作为一个完整性测试。这绝对不是我希望的那么简单,但组合应该让我至少90%确定用户的时区。

答案 1 :(得分:24)

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

通过结合这些事实,您可以快速找出每个拉链的时区列表。

以下是zip code ranges per state的列表,以及states per time zone的列表。

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

您正在处理的大多数非美国国家可能只属于一个时区。您可能想要查看前N名非美国访客的来源,并查看他们的时区。

答案 2 :(得分:11)

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

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

它来自四个地点(主要Yahoo PlaceFinder API - 感谢@Chris N)

有关更多信息和说明,请参阅自述文件。

答案 3 :(得分:8)

如果您愿意,还可以通过询问浏览器来了解时区 约什弗雷泽有a nice write up on it here

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)。由于夏季期间始终遵守夏令时,我们可以将1月份两个日期之间的时间偏差与6月份两个日期之间的时间偏差进行比较。如果偏移量不同,那么我们知道该位置遵守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。

这可能对您在美国以外的客户有所帮助,而且可能会有所补充 你的拉链方式。

Here is a SO questions that touch on getting the timezone from javascript

答案 4 :(得分:4)

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

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

速度快,体积小,没有外部依赖关系,但请记住,邮政编码不能完美映射到时区。

答案 5 :(得分:4)

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

它们需要查询字符串上的unix时间戳。从返回的响应中可以看出timeZoneName根据时间戳考虑了夏令时,而timeZoneId是时区的独立于DST的名称。

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

我相信PHP同样可以找到" America / New_York"在http://pecl.php.net/package/timezonedb

答案 6 :(得分:2)

我最近made a Ruby hash of all the zipcodes in the US and their associated timezones,如果您对此感兴趣,可以使用{{3}}。为了您的目的,应该很容易进行逆向工程。

答案 7 :(得分:1)

答案 8 :(得分:1)

我一直在为自己的网站解决这个问题,感觉我已经找到了一个非常好的解决方案

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

然后

2a)对剩余的状态使用js解决方案(Javascript/PHP and timezones

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

通过这种方式,您可以为大多数用户找到便宜(并且非常准确!)的tz,然后使用其他一种更昂贵的方法将其用于其他州。

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

答案 9 :(得分:1)

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

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

    P.S。无法插入所有链接:(请使用搜索。

答案 10 :(得分:1)

我维护一个名为Zipgenius的zipcode-to-timezone API,它使用上面提供的@chriv提供的数据。请随意使用它。

答案 11 :(得分:0)

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

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

答案 12 :(得分:0)

这将下载一个yaml文件,将所有时区映射到其zipcodes数组:

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

e.g。

"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

e.g。

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

答案 13 :(得分: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"
}