NAME
Geo::Postcode - UK Postcode validation and location
SYNOPSIS
use Geo::Postcode;
my $postcode = Geo::Postcode->new('SW1 1AA');
return unless $postcode->valid;
my ($n, $e) = ($postcode->gridn, $postcode->gride);
# is the same as
my ($n, $e) = $postcode->coordinates;
# and alternative to
my @location = ($postcode->lat, $postcode->long);
# or the impatient can skip the construction step:
my ($n, $e) = Geo::Postcode->coordinates('SW1 1AA');
my $clean_postcode = Geo::Postcode->valid( $postcode );
my ($area, $district, $sector, $unit) = Geo::Postcode->analyse('SW1 1AA');
DESCRIPTION
Geo::Postcode will accept full or partial UK postcodes, validate them against the official spec, separate them into their component parts, translate them into map references and calculate distances between them.
It does not check whether the supplied postcode exists: only whether it is well-formed according to British Standard 7666, which you can find here:
http://www.govtalk.gov.uk/gdsc/html/frames/PostCode.htm
GP will also work with partial codes, ie areas, districts and sectors. They won't validate, but you can still test them for legitimacy with a call to valid_fragment
, and you can still turn them into grid references.
To work with US zipcodes, you need Geo::Postalcode instead.
GRID REFERENCES AND DATA FILES
Any postcode, whether fully or partly specified, can be turned into a grid reference. The Post Office calls it a centroid, and it marks the approximate centre of the area described by the code.
Unfortunately, and inexplicably, this information is not public domain: unless you're prepared to work at a very crude level, you have to buy location data either from the Post Office or a data shop.
This module comes with with a basic set of publicly-available coordinates that covers nearly all the postcode districts (ie it maps the first block of the postcode but not the second).
This means that the coordinates we return and the distances we calculate are a bit crude, being based at best on the postcode area. See the POD for Geo::Delivery::Location for how to override the standard data set something more comprehensive.
INTERFACE
This is a mostly vanilla OOP module, but for quick and dirty work you can skip the object construction step and call a method directly with a postcode string. It will build the necessary object behind the scenes and return the result of the operation.
my @coordinates = Geo::Postcode->coordinates('LA23 3PA');
my $postcode = Geo::Postcode->valid($input->param('postcode'));
The object will not be available for any more requests, of course.
INTERNALS
The main Geo::Postcode object is very simple blessed hashref. The postcode information is stored as a four-element listref in $self->{postcode}. Location information is handled by the separate Geo::Postcode::Location, which by default uses a simple DB file but can easily be overridden to use the data source of your choice.
CONSTRUCTION
new ( postcode_string )
Constructs and returns the very simple postcode object. All other processing and loading is deferred until a method is called.
postcode_string ( )
Always returns the postcode string with which the object was constructed, but uppercased. Cannot be set after construction.
fragments ( )
Breaks the postcode into its significant parts, eg:
EC1R 8DH --> | EC | 1R | 8 | DH |
Stores the parts for later reference and returns them as a listref. Most other methods in this class call fragments() first to get their raw material.
LOCATION
The grid-reference mapping is handled by Geo::Postcode::Location, which is only loaded when required. This is because it comes with its own database of very basic location information, and you won't want to load that unless you want to. It also makes it easier to subclass the location functions and use your own data source.
The first call to a location-related method of Geo::Postcode will cause the location class to be loaded, along with its data file, and a location object to be associated with this postcode object. We then pass all location-related queries on to the location object.
The accuracy of the information returned by location methods depends on the resolution of the location data file: see the POD for Geo::Postcode::Location for how to supply your own dataset instead of using the crude set that comes with this module.
location_class ()
Returns the full name of the class that should be called to get a location object.
location ()
Returns - and if necessary, creates - the location object associated with this postcode object.
gridn () gride ()
Return the OS grid reference coordinates of the centre of this postcode.
gridref ()
Return the proper OS grid reference for this postcode, in classic AA123456 style.
lat () long ()
Return the latitude and longitude of the centre of this postcode.
placename () ward () nhsarea ()
Return information from other fields that may or may not be present in your dataset. The default set supplied with this module doesn't have these extra fields but a set derived from the PAF normally will.
coordinates ()
Return the grid reference x, y coordinates of this postcode as two separate values. The grid reference we use here are completely numerical: the usual OS prefix is omitted and an absolute coordinate value returned unless you call gridref
.
distance_from ( postcode object or string, unit )
Accepts a postcode object or string, and returns the distance from here to there.
As usual, you can call this method directly (ie without first constructing an object):
my $distance = Geo::Postcode->distance_from('LA23 3PA', 'EC1Y 8PQ');
Will do what you would expect. distance_between
is provided as a synonym of distance_from
to make that read more sensibly:
my $distance = Geo::Postcode->distance_between('LA23 3PA', 'EC1Y 8PQ');
And in any of these cases you can supply an additional parameter dictating the units of distance: the options are currently 'miles', 'm' or 'km' (the default).
my $distance = Geo::Postcode->distance_between('LA23 3PA', 'EC1Y 8PQ', 'miles');
The same thing can be accomplished by setting $Geo::Postcode::Location::units
if you don't mind acting global.
bearing_to ( postcode objects or strings)
Accepts a list of postcode objects and/or strings, and returns a corresponding list of the bearings from here to there, as degrees clockwise from grid North.
friendly_bearing_to ( postcode objects or strings)
Accepts a list of postcode objects and/or strings, and returns a corresponding list of rough directions from here to there. 'NW', 'ESE'. That sort of thing.
print "That's " . $postcode1->distance_to($postcode2) . " km " .
$postcode1->friendly_bearing_to($postcode2) . " of here.";
VALIDATION
Postcodes are checked against BS7666, which specifies the various kinds of sequences allowed and the characters which may appear in each position.
valid ()
If the postcode is well-formed and complete, this method returns true (in the useful form of the postcode itself, properly formatted). Otherwise, returns false.
valid_fragment ()
A looser check that doesn't mind incomplete postcodes. It will test that area, district or sector codes respect the rules for valid characters in that part of the postcode, and return true unless it finds anything that's not allowed.
SEGMENTATION
These methods provide the various sector, area and district codes that can be derived from a full postcode, each of which identifies a larger area that encloses the postcode area.
analyse ()
Returns a list of all the codes present in this postcode, in descending order of specificity. So:
Geo::Postcode->analyse('EC1Y8PQ');
will return:
('EC1Y 8PQ', 'EC1Y 8', 'EC1Y', 'EC')
which is useful mostly for dealing with situations where you don't know what resolution will be required and need to try alternatives. We do this when location-finding, since the resolution of your location data may vary and cannot be predicted.
area ()
Returns the area code part of this postcode. This is the broadest area of all and is identified by the first one or two letters of the code: 'E' or 'EC' or 'LA' or whatever.
district ()
Returns the district code part of this postcode. This is also called the 'outward' part, by the post office: it consists of the first two or three characters and identifies the delivery office for this address. It will look like 'LA23' or 'EC1Y'.
sector ()
Returns the sector code part of this postcode. This is getting more local: it includes the first part of the code and the first digit of the second part, and is apparent used by the delivery office to sort the package. It will look something like 'EC1Y 8' or 'E1 7', and note that the space is meaningful. 'E1 7' and 'E17' are not the same thing.
unit ()
Returns the whole postcode, properly formatted (ie in caps and with a space in the right place, regardless of how it came in).
This is similar to what you get just by stringifying the postcode object, with the important difference that unit() will only work for a well-formed postcode:
print Geo::Postcode->unit('LA233PA'); # prints LA23 3PA
print Geo::Postcode->new('LA233PA'); # prints LA23 3PA
print Geo::Postcode->unit('LA23333'); # prints nothing
print Geo::Postcode->new('LA23333'); # prints LA23
Whereas normal stringification - which calls _as_string
will print all the valid parts of a postcode.
special_cases ()
Returns a list of known valid but non-conformist postcodes. The only official one is 'G1R 0AA', the old girobank address, but you can override this method to extend the list.
AUTHOR
William Ross, wross@cpan.org
COPYRIGHT
Copyright 2004 William Ross, spanner ltd.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.