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

Replies are listed 'Best First'.
Re: Get latitude and longitude from Canadian postal codes
by jwkrahn (Abbot) on Mar 23, 2007 at 21:47 UTC
    unless ($line =~ m/([A-Z]\d[A-Z]\s*\d[A-Z]\d)/i) {

    Your pattern is over-broad for a Canadian postal code (see: Canadian postal code)  You probably want something like:
    unless ( $line =~ m/([ABCEGHJ-NPRSTVXY][0-9][ABCEGHJ-NPRSTV-Z]\s*[0-9] +[ABCEGHJ-NPRSTV-Z][0-9])/i ) {