Ted Byers wrote: > I am presently looking at a few perl packages that should facilitate > developing such a package (which I will do in due course if no-one > identifies one that already exists - I haven't found one).
Existing Geo and DateTime Perl modules will do what you said you needed done: look up time zones by city names and then use those time zones in date and time computations. There's no need to write a new module. > The packages I am looking at are: > > Geo::GeoNames > Geo::GeoNames::File > Geo::Query::LatLong > Geo::Location::TimeZone > > I figure the first two provide for two different ways to use the geonames > data. The first uses the geoNames web services (and requires you to sign > up for an account - I do not know how long that will continue to be > available without cost), and the second provides a way to use the same data > from one of their data files that you have downloaded to your own system. > I see the second two being a fallback solution if the city in question is > not in the geonames database. Geo::Query::LatLong lets you get the > latitude and longitude of a city and Geo::Location::TimeZone gives you the > timezone for a given position sepcified by latitude and longitude. This > strikes me as more sensible, and almost certainly faster, than trying to > find the city in the oslen db that is closest to the city for which you > want the timezone. > > The overall logic would be to first see if the city for which you want a > timezone is in the Olson DB. If not, check geonames, and if that fails, > use the latitude and longitude of the city to get a timezone. The Olson tz database (now, properly, the IANA Time Zone Database) is a database of time zones, not a database of cities. The uniform convention designed by Paul Eggert to name time zones in the database typically includes the name of a representative city within the region defined by the time zone. So which city within the region is used in the name of the time zone? The Wikipedia article titled "tz database" explains: Usually the most populous city in a region is chosen to represent the entire time zone, although other cities may be selected if they are more widely known or result in a less ambiguous name. ... The location selected is representative for the entire area. http://en.wikipedia.org/wiki/Tz_database#Location Yitzchak Scott-Thoennes explained this in a reply to your datetime mailing list inquiry about this same topic in August 2009. He wrote: Within each zone, the most "recognizable" city is used as the name. In some cases, this isn't the largest. See the comments in the region files for rationales. http://www.nntp.perl.org/group/perl.datetime/2009/08/msg7333.html > I am also looking at loading the GeoNames data into my databases > (Postgresql and MySQL), and accessing that directly instead of accessing > it from a text file: this would be to determine which is faster. Consider SQLite. There's an existing module named Geo::GeoNames::DB::SQLite. > One of the tasks I suppose I will have to do is check to see how many of > the time zones in these other sources are incompatible with those in the > Olson DB, and then find a mapping of them to the Olson timezones. All you need to determine which time zone a city is in is a database of of time zones by location. The GeoNames geographical database is just such a database. It uses the Olson tz database time zones and time zone names. There are no "incompatible" time zones in the GeoNames database. I wrote a small proof-of-concept Perl script using Geo::GeoNames and DateTime to demonstrate how to look up time zones by city names and then use those time zones to instantiate DateTime objects. -------------------------------------------------------------------------- C:\Demo>cat now.pl #!perl use strict; use warnings; use DateTime; use Geo::GeoNames; use URI::Escape; binmode STDOUT, ':encoding(UTF-8)'; my $city = @ARGV ? shift : 'Tempe'; my $geo = Geo::GeoNames->new( username => '*********' ); my $result = $geo->search( q => uri_escape_utf8($city), maxRows => 1, style => 'FULL' ); defined $result->[0] or die "Unrecognized city '$city'\n"; my $city_name = $result->[0]->{name}; my $country_name = $result->[0]->{countryName}; my $time_zone = $result->[0]->{timezone}{content}; my $time_now = DateTime->now( time_zone => $time_zone ); print "$city_name ($country_name) $time_now ($time_zone)\n"; exit 0; C:\Demo>now Tempe (United States) 2012-08-18T20:47:15 (America/Phoenix) C:\Demo>now Flagstaff Flagstaff (United States) 2012-08-18T20:47:20 (America/Phoenix) C:\Demo>now "Window Rock" Window Rock (United States) 2012-08-18T21:47:26 (America/Shiprock) C:\Demo>now "Salt Lake City" Salt Lake City (United States) 2012-08-18T21:47:34 (America/Denver) C:\Demo>now "New York" New York (United States) 2012-08-18T23:47:42 (America/New_York) C:\Demo>now "Washington D.C." Washington (United States) 2012-08-18T23:47:52 (America/New_York) C:\Demo>now Saratoga Saratoga Springs (United States) 2012-08-18T23:48:15 (America/New_York) C:\Demo>now Baden-Württemberg Baden-Baden (Germany) 2012-08-19T05:49:11 (Europe/Berlin) C:\Demo>now Yūbari | cat -Uc8pa Yūbari-shi (Japan) 2012-08-19T12:50:41 (Asia/Tokyo) C:\Demo>now Bombay Mumbai (India) 2012-08-19T09:21:11 (Asia/Kolkata) C:\Demo>now Calcutta Kolkata (India) 2012-08-19T09:21:19 (Asia/Kolkata) C:\Demo>now "New Delhi" New Delhi (India) 2012-08-19T09:21:29 (Asia/Kolkata) C:\Demo>now Timbuktu Timbuktu (Mali) 2012-08-19T03:51:49 (Africa/Bamako) C:\Demo>now "Lake Chaubunagungamaug" Lake Chaubunagungamaug (United States) 2012-08-18T23:52:34 (America/New_York) C:\Demo>now Chargoggagoggmanchauggagoggchaubunagungamaugg Unrecognized city 'Chargoggagoggmanchauggagoggchaubunagungamaugg' C:\Demo> -------------------------------------------------------------------------- Arizona is in the U.S. Mountain Time Zone, but Arizona doesn't observe daylight saving time. So Tempe and Flagstaff are in the 'America/Phoenix' time zone, not the 'America/Denver' time zone. Window Rock is in Arizona, but it's also in the Navajo Nation. Unlike the rest of Arizona, the Navajo Nation observes daylight saving time. So Window Rock is in the 'America/Shiprock' time zone. As it happens, Shiprock, a representative location in the Navajo Nation, is in New Mexico, not in Arizona. Salt Lake City is a big, well-known city that, like Phoenix, is in the U.S. Mountain Time Zone. But Utah observes daylight saving time, so Salt Lake City is in the 'America/Denver' time zone. When you look up Bombay in the GeoNames geographical database, you get Mumbai. When you look up Calcutta, you get Kolkata. When you look up New Delhi, you get New Delhi. All of these cities in India are in the 'Asia/Kolkata' time zone. Jim Monty
