A friend does some geographic statistics stuff. He told me he was manually entering postal codes into a program one at a time to get the latitude and longitude.
I figured there might be a module on CPAN. I wrote a short program using
Geo::Coder::Canada for him to use. It reads from stdin so I just piped a CSV file he gave me into the program.
It turned out he wanted a CSV file to import into a spreadsheet. By then I already had the human readable output and each postal code takes a second to lookup so I used
Emacs rectangle functions to fix up the columns but it would be easy to change the code to print the results in CSV.
The code finds the first postal code on each line of input so it's kind of smart when fed a full address or quotes around the postal code. A sample run looks like:
$ ./geocode-canada.pl
Enter a Canadian Postal Code and press enter.
Repeat until you are done. Press control-c or control-d to exit.
t2s 0b3
t2s 0b3 , Lat: 51.037821 , Long: -114.074626
t2e0c1
t2e0c1 , Lat: 51.053263 , Long: -114.045510
T3C 0X7
T3C 0X7 , Lat: 51.039459 , Long: -114.092120
"T3E 0B1"
T3E 0B1 , Lat: 51.037782 , Long: -114.128998
No postal code found in input
2500 University Drive N.W.
No postal code found in input
Calgary, Alberta,
No postal code found in input
T2N 1N4
T2N 1N4 , Lat: 51.074892 , Long: -114.129012
Update: Thanks to
jwkrahn for making the regex that looks for a valid postal code more specific.
The code is:
#! /usr/bin/perl -w
# file: geocode-canada.pl
# purpose: find Lat/Lon values from Canadian postal code values
use strict;
use Data::Dumper;
use Geo::Coder::Canada;
print qq/
Enter a Canadian Postal Code and press enter.
Repeat until you are done. Press control-c or control-d to exit.
/;
LINE: while(my $line = <>) {
my $postal;
# improved by jwkrahn
# unless ($line =~ m/([A-Z]\d[A-Z]\s*\d[A-Z]\d)/i) {
unless ( $line =~ m/([ABCEGHJ-NPRSTVXY][0-9][ABCEGHJ-NPRSTV-Z]\s*[
+0-9][ABCEGHJ-NPRSTV-Z][0-9])/i ) {
print "No postal code found in input\n";
next LINE;
}
$postal = $1;
my $g = Geo::Coder::Canada->new;
$g->postal($postal);
if ($g->geocode) {
#print Dumper($g);
my $result = $g->geo_result();
my $latitude = $result->latt;
my $longitude = $result->longt;
print $g->postal(), "\t, Lat: " , $latitude , "\t, Long: " , $
+longitude , "\n";
} else {
#print Dumper($g);
my $geodata = $g->geodata();
#print Dumper($geodata);
print $geodata->{error}->{description} ,
"(code ", $geodata->{error}->{code} , ")" ,
"\n";
}
}