Geography::States - Map states and provinces to their codes, and vica versa.


Geography-States documentation Contained in the Geography-States distribution.

Index


Code Index:

NAME

Top

Geography::States - Map states and provinces to their codes, and vica versa.

SYNOPSIS

Top

 use Geography::States;

 my $obj = Geography::States -> new (COUNTRY [, STRICT]);




EXAMPLES

Top

 my $canada = Geography::States -> new ('Canada');

 my  $name          =  $canada -> state ('NF');      # Newfoundland.
 my  $code          =  $canada -> state ('Ontario'); # ON.
 my ($code, $name)  =  $canada -> state ('BC');      # BC, British Columbia.
 my  @all_states    =  $canada -> state;             # List code/name pairs.




DESCRIPTION

Top

This module lets you map states and provinces to their codes, and codes to names of provinces and states.

The Geography::States - new ()> call takes 1 or 2 arguments. The first, required, argument is the country we are interested in. Current supported countries are USA, Brazil, Canada, The Netherlands, and Australia. If a second non-false argument is given, we use strict mode. In non-strict mode, we will map territories and alternative codes as well, while we do not do that in strict mode. For example, if the country is USA, in non-strict mode, we will map GU to Guam, while in strict mode, neither GU and Guam will be found.

The state() method

All queries are done by calling the state method in the object. This method takes an optional argument. If an argument is given, then in scalar context, it will return the name of the state if a code of a state is given, and the code of a state, if the argument of the method is a name of a state. In list context, both the code and the state will be returned.

If no argument is given, then the state method in list context will return a list of all code/name pairs for that country. In scalar context, it will return the number of code/name pairs. Each code/name pair is a 2 element anonymous array.

Arguments can be given in a case insensitive way; if a name consists of multiple parts, the number of spaces does not matter, as long as there is some whitespace. (That is "NewYork" is wrong, but "new    YORK" is fine.)

ODDITIES AND OPEN QUESTIONS

Top

I found conflicting abbreviations for the US Northern Mariana Islands, listed as NI and MP. I picked MP from the USPS site.

One site listed Midway Islands as having code MD. It is not listed by the USPS site, and because it conflicts with Maryland, it is not put in this listing.

The USPS also has so-called Military "States", with non-unique codes. Those are not listed here.

Canada's Quebec has two codes, the older PQ and the modern QC. Both PQ and QC will map to Quebec, but Quebec will only map to QC. With strict mode, PQ will not be listed. Similary, Newfoundland has an old code NF, and a new code NL (the province is now called Newfoundland and Labrador).

DEVELOPMENT

Top

The current sources of this module are found on github, git://github.com/Abigail/geography--states.git.

AUTHOR

Top

Abigail mailto:geography-states@abigail.be.

COPYRIGHT and LICENSE

Top


Geography-States documentation Contained in the Geography-States distribution.

package Geography::States;

use 5.006;

use strict;
use warnings;
no  warnings 'syntax';

our $VERSION = '2009040901';

my %states;

sub _c_length ($) {
    lc $_ [0] eq "australia" ? 3 : 2
}

sub _norm ($$) {
    my ($str, $country) = @_;
    if (_c_length ($country) >= length $str) {
        $str =  uc $str;
    }
    else {
        $str =  join " " => map {ucfirst lc} split /\s+/ => $str;
        $str =~ s/\bOf\b/of/         if $country eq lc 'USA';
        $str =~ s/\bD([eo])\b/d$1/   if $country eq lc 'Brazil';
    }

    $str;
}

# This was originally wrapped in an INIT block, to avoid having it
# run when only compilation was wanted. However, that seems to fail
# when used in combination with mod_perl.
my $country;
while (<DATA>) {
    chomp;
    last if $_ eq '__END__';
    s/#.*//;
    next unless /\S/;
    if (/^<(.*)>/) {
        $country =  lc $1;
        $country =~ s/\s+/ /g;
        next;
    }
    my ($code, $state) = split /\s+/ => $_, 2;
    next unless defined $state;
    my $fake = $code =~ s/\*$//;
    my $info = [$code, $state, $fake];
    $states {$country} -> {_norm ($code,  $country)} = $info;
    $states {$country} -> {_norm ($state, $country)} = $info;
}

sub new {
    die "Not enough arguments for Geography::States -> new ()\n" unless @_ > 1;

    my $proto   =  shift;
    my $class   =  ref $proto || $proto;

    my $country =  lc shift;
       $country =~ s/\s+/ /g;

    die "No such country $country\n" unless $states {$country};

    my $strict  =  shift;

    my $self;
    my ($cs, $info);
    while (($cs, $info) = each %{$states {$country}}) {
        next unless $cs eq $info -> [0];
        next if $strict && $info -> [2];
        my $inf = [@$info [0, 1]];
        foreach my $i (0 .. 1) {
            $self -> {cs} -> {$info -> [$i]} = $inf unless
                       exists $self -> {cs} -> {$info -> [$i]};
        }
    }
    $self -> {country} = $country;

    bless $self => $class;
}


sub state {
    my $self = shift;
    unless (@_) {
        my %h;
        return grep {!$h {$_} ++} values %{$self -> {cs}};
    }
    my $query  =  _norm shift, $self -> {country};
    my $answer =  $self -> {cs} -> {$query} or return;
    return @$answer if wantarray;
    $answer -> [$answer -> [0] eq $query ? 1 : 0];
}


1;
    
__DATA__
# Information from USPS Abbreviations.
<USA>
AK	Alaska
AL	Alabama
AR	Arkansas
AS*     American Samoa
AZ	Arizona
CA	California
CO	Colorado
CT	Connecticut
DC*     District of Columbia
DE	Delaware
FL	Florida
FM*     Federated States of Micronesia
GA	Georgia
GU*     Guam
HI	Hawaii
IA	Iowa
ID	Idaho
IL	Illinois
IN	Indiana
KS	Kansas
KY	Kentucky
LA	Louisiana
MA	Massachusetts
MD	Maryland
ME	Maine
MH*     Marshall Islands
MI	Michigan
MN	Minnesota
MO	Missouri
# I found this listed as NI as well; which makes more sense.
MP*     Northern Mariana Islands
MS	Mississippi
MT	Montana
# The USPS site doesn't list this, and MD is already taken.
# MD*     Midway Islands
NC	North Carolina
ND	North Dakota
NE	Nebraska
NH	New Hampshire
NJ	New Jersey
NM	New Mexico
NV	Nevada
NY	New York
OH	Ohio
OK	Oklahoma
OR	Oregon
PA	Pennsylvania
PR*     Puerto Rico
PW*     Palau
RI	Rhode Island
SC	South Carolina
SD	South Dakota
TN	Tennessee
TX	Texas
UT	Utah
VA	Virginia
VI*     Virgin Islands
VT	Vermont
WA	Washington
WI	Wisconsin
WV	West Virginia
WY	Wyoming
<Brazil>
AC	Acre
AL	Alagoas
AM	Amazonas
AP	Amapá
BA	Bahia
CE	Ceará
DF	Distrito Federal
ES	Espiríto Santo
FN	Fernando de Noronha
GO	Goiás
MA	Maranhão
MG	Minas Gerais
MS	Mato Grosso do Sul
MT	Mato Grosso
PA	Pará
PB	Paraíba
PE	Pernambuco
PI	Piauí
PR	Paraná
RJ	Rio de Janeiro
RN	Rio Grande do Norte
RO	Rondônia
RR	Roraima
RS	Rio Grande do Sul
SC	Santa Catarina
SE	Sergipe
SP	São Paulo
TO	Tocantins
<Canada>
AB	Alberta
BC	British Columbia
MB	Manitoba
NB	New Brunswick
NF*	Newfoundland
NL	Newfoundland and Labrador
NS	Nova Scotia
NT	Northwest Territories
NU	Nunavut
ON	Ontario
PE	Prince Edward Island
PQ*     Quebec
QC	Quebec
SK	Saskatchewan
YT	Yukon Territory
<The Netherlands>
DR      Drente
FL      Flevoland
FR      Friesland
GL      Gelderland
GR      Groningen
LB      Limburg
NB      Noord Brabant
NH      Noord Holland
OV      Overijssel
UT      Utrecht
ZH      Zuid Holland
ZL      Zeeland
# Supplied by Kirrily "Skud" Robert
<Australia>
ACT     Australian Capital Territory
NSW     New South Wales
QLD     Queensland
SA      South Australia
TAS     Tasmania
VIC     Victoria
WA      Western Australia
__END__