{"id":18909979,"url":"https://github.com/jonasbn/bdkpst","last_synced_at":"2026-03-06T15:03:52.221Z","repository":{"id":12318702,"uuid":"14954445","full_name":"jonasbn/bdkpst","owner":"jonasbn","description":"Business::DK::Postalcode - validation of Danish postal codes","archived":false,"fork":false,"pushed_at":"2025-05-25T17:07:55.000Z","size":311,"stargazers_count":1,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-18T13:45:26.593Z","etag":null,"topics":["hacktoberfest","perl","perl5","validation"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonasbn.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2013-12-05T13:38:10.000Z","updated_at":"2025-05-25T17:07:38.000Z","dependencies_parsed_at":"2023-11-29T06:22:16.867Z","dependency_job_id":"20dfec7f-20a7-44f3-941d-60eaf43bfd2d","html_url":"https://github.com/jonasbn/bdkpst","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/jonasbn/bdkpst","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasbn%2Fbdkpst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasbn%2Fbdkpst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasbn%2Fbdkpst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasbn%2Fbdkpst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonasbn","download_url":"https://codeload.github.com/jonasbn/bdkpst/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasbn%2Fbdkpst/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30182686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T14:42:24.748Z","status":"ssl_error","status_checked_at":"2026-03-06T14:42:14.925Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","perl","perl5","validation"],"created_at":"2024-11-08T09:38:52.215Z","updated_at":"2026-03-06T15:03:52.197Z","avatar_url":"https://github.com/jonasbn.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CPAN version](https://badge.fury.io/pl/Business-DK-Postalcode.svg)](http://badge.fury.io/pl/Business-DK-Postalcode)\n[![Build Status](https://travis-ci.org/jonasbn/bdkpst.svg?branch=master)](https://travis-ci.org/jonasbn/bdkpst)\n[![Coverage Status](https://coveralls.io/repos/jonasbn/bdkpst/badge.png?branch=master)](https://coveralls.io/r/jonasbn/bdkpst?branch=master)\n\n# NAME\n\nBusiness::DK::Postalcode - Danish postal code validator and container\n\n# VERSION\n\nThis documentation describes version 0.08\n\n# SYNOPSIS\n\n    # basic validation of string\n    use Business::DK::Postalcode qw(validate);\n\n    if (validate($postalcode)) {\n        print \"We have a valid Danish postalcode\\n\";\n    } else {\n        warn \"Not a valid Danish postalcode\\n\";\n    }\n\n\n    # basic validation of string, using less intrusive subroutine\n    use Business::DK::Postalcode qw(validate_postalcode);\n\n    if (validate_postalcode($postalcode)) {\n        print \"We have a valid Danish postal code\\n\";\n    } else {\n        warn \"Not a valid Danish postal code\\n\";\n    }\n\n\n    # using the untainted return value\n    use Business::DK::Postalcode qw(validate_postalcode);\n\n    if (my $untainted = validate_postalcode($postalcode)) {\n        print \"We have a valid Danish postal code: $untainted\\n\";\n    } else {\n        warn \"Not a valid Danish postal code\\n\";\n    }\n\n\n    # extracting a regex for validation of Danish postal codes\n    use Business::DK::Postalcode qw(create_regex);\n\n    my $regex_ref = ${create_regex()};\n\n    if ($postalcode =~ m/$regex/) {\n        print \"We have a valid Danish postal code\\n\";\n    } else {\n        warn \"Not a valid Danish postal code\\n\";\n    }\n\n\n    # All postal codes for use outside this module\n    use Business::DK::Postalcode qw(get_all_postalcodes);\n\n    my @postalcodes = @{get_all_postalcodes()};\n\n\n    # All postal codes and data for use outside this module\n    use Business::DK::Postalcode qw(get_all_data);\n\n    my $postalcodes = get_all_data();\n\n    foreach (@{postalcodes}) {\n        printf\n            'postal code: %s city: %s street/desc: %s company: %s province: %d country: %d', split /\\t/, $_, 6;\n    }\n\n# FEATURES\n\n- Providing list of Danish postal codes and related area names\n- Look up methods for Danish postal codes for web applications and the like\n\n# DESCRIPTION\n\nThis distribution is not the original resource for the included data, but simply\nacts as a simple distribution for Perl use. The central source is monitored so this\ndistribution can contain the newest data. The monitor script (`postdanmark.pl`) is\nincluded in the distribution.\n\nThe data are converted for inclusion in this module. You can use different extraction\nsubroutines depending on your needs:\n\n- [\"get\\_all\\_data\"](#get_all_data), to retrieve all data, data description below in [\"Data\"](#data).\n- [\"get\\_all\\_postalcodes\"](#get_all_postalcodes), to retrieve all postal codes\n- [\"get\\_all\\_cities\"](#get_all_cities), to retieve all cities\n- [\"get\\_postalcode\\_from\\_city\"](#get_postalcode_from_city), to retrieve one or more postal codes from a city name\n- [\"get\\_city\\_from\\_postalcode\"](#get_city_from_postalcode), to retieve a city name from a postal code\n\n## Data\n\nHere follows a description of the included data, based on the description from\nthe original source and the authors interpretation of the data, including\ndetails on the distribution of the data.\n\n### city name\n\nA non-unique, case-sensitive representation of a city name in Danish.\n\n### street/description\n\nThis field is either a streetname or a description, is it only provided for\na few special records.\n\n### company name\n\nThis field is only provided for a few special records.\n\n### province\n\nThis field is a bit special and it's use is expected to be related to distribution\nall entries inside Copenhagen are marked as 'False' in this column and 'True' for\nall entries outside Copenhagen - and this of course with exceptions. The data are\nincluded since they are a part of the original data.\n\n### country\n\nSince the original source contains data on 3 different countries:\n\n- Denmark\n- Greenland\n- Faroe Islands\n\nOnly the data representing Denmark has been included in this distribtion, so this\nfield is always containing a one.\n\nFor access to the data on Greenland or Faroe Islands please refer to: [Business::GL::Postalcode](https://metacpan.org/pod/Business::GL::Postalcode)\nand [Business::FO::Postalcode](https://metacpan.org/pod/Business::FO::Postalcode) respectfully.\n\n## Encoding\n\nThe data distributed are in Danish for descriptions and names and these are encoded in UTF-8.\n\n# EXAMPLES\n\nA web application example is included in the examples directory following this distribution\nor available at [https://metacpan.org/pod/Business::DK::Postalcode](https://metacpan.org/pod/Business::DK::Postalcode).\n\n# SUBROUTINES AND METHODS\n\n## validate\n\nA simple validator for Danish postal codes.\n\nTakes a string representing a possible Danish postal code and returns either\n**1** or **0** indicating either validity or invalidity.\n\n    my $rv = validate(2665);\n\n    if ($rv == 1) {\n        print \"We have a valid Danish postal code\\n\";\n    } ($rv == 0) {\n        print \"Not a valid Danish postal code\\n\";\n    }\n\n## validate\\_postalcode\n\nA less intrusive subroutine for import. Acts as a wrapper of [\"validate\"](#validate).\n\n    my $rv = validate_postalcode(2300);\n\n    if ($rv) {\n        print \"We have a valid Danish postal code\\n\";\n    } else {\n        print \"Not a valid Danish postal code\\n\";\n    }\n\n## get\\_all\\_data\n\nReturns a reference to a a list of strings, separated by tab characters. See\n[\"Data\"](#data) for a description of the fields.\n\n    use Business::DK::Postalcode qw(get_all_data);\n\n    my $postalcodes = get_all_data();\n\n    foreach (@{postalcodes}) {\n        printf\n            'postalcode: %s city: %s street/desc: %s company: %s province: %d country: %d', split /\\t/, $_, 6;\n    }\n\n## get\\_all\\_postalcodes\n\nTakes no parameters.\n\nReturns a reference to an array containing all valid Danish postal codes.\n\n    use Business::DK::Postalcode qw(get_all_postalcodes);\n\n    my $postalcodes = get_all_postalcodes;\n\n    foreach my $postalcode (@{$postalcodes}) { ... }\n\n## get\\_all\\_cities\n\nTakes no parameters.\n\nReturns a reference to an array containing all Danish city names having a postal code.\n\n    use Business::DK::Postalcode qw(get_all_cities);\n\n    my $cities = get_all_cities;\n\n    foreach my $city (@{$cities}) { ... }\n\nPlease note that this data source used in this distribution by no means is authorative\nwhen it comes to cities located in Denmark, it might have all cities listed, but\nunfortunately also other post distribution data.\n\n## get\\_city\\_from\\_postalcode\n\nTakes a string representing a Danish postal code.\n\nReturns a single string representing the related city name or an empty string indicating nothing was found.\n\n    use Business::DK::Postalcode qw(get_city_from_postalcode);\n\n    my $zipcode = '2300';\n\n    my $city = get_city_from_postalcode($zipcode);\n\n    if ($city) {\n        print \"We found a city for $zipcode\\n\";\n    } else {\n        warn \"No city found for $zipcode\";\n    }\n\n## get\\_postalcode\\_from\\_city\n\nTakes a string representing a Danish city name.\n\nReturns a reference to an array containing zero or more postal codes related to that city name. Zero indicates nothing was found.\n\nPlease note that city names are not unique, hence the possibility of a list of postal codes.\n\n    use Business::DK::Postalcode qw(get_postalcode_from_city);\n\n    my $city = 'København K';\n\n    my $postalcodes = get_postalcode_from_city($city);\n\n    if (scalar @{$postalcodes} == 1) {\n        print \"$city is unique\\n\";\n    } elsif (scalar @{$postalcodes} \u003e 1) {\n        warn \"$city is NOT unique\\n\";\n    } else {\n        die \"$city not found\\n\";\n    }\n\n## create\\_regex\n\nThis method returns a generated regular expression for validation of a string\nrepresenting a possible Danish postal code.\n\n    use Business::DK::Postalcode qw(create_regex);\n\n    my $regex_ref = ${create_regex()};\n\n    if ($postalcode =~ m/$regex/) {\n        print \"We have a valid Danish postalcode\\n\";\n    } else {\n        print \"Not a valid Danish postalcode\\n\";\n    }\n\n# PRIVATE SUBROUTINES AND METHODS\n\n## \\_retrieve\\_cities\n\nTakes a reference to an array based on the DATA section and return a reference\nto an array containing only city names.\n\n### \\_retrieve\\_postalcode\n\nTakes a reference to an array based on the DATA section and return a reference\nto an array containing only postal codes.\n\n### \\_build\\_tree\n\nInternal method to assist [\"create\\_regex\"](#create_regex) in generating the regular expression.\n\nTakes a [https://metacpan.org/pod/Tree::Simple](https://metacpan.org/pod/Tree::Simple) object and a reference to an array of data elements.\n\n# DIAGNOSTICS\n\nThere are not special diagnostics apart from the ones related to the different\nsubroutines.\n\n# CONFIGURATION AND ENVIRONMENT\n\nThis distribution requires no special configuration or environment.\n\n# DEPENDENCIES\n\n- [https://metacpan.org/pod/Carp](https://metacpan.org/pod/Carp) (core)\n- [https://metacpan.org/pod/Exporter](https://metacpan.org/pod/Exporter) (core)\n- [https://metacpan.org/pod/Tree::Simple](https://metacpan.org/pod/Tree::Simple)\n- [https://metacpan.org/pod/Params::Validate](https://metacpan.org/pod/Params::Validate)\n\n## TEST\n\nPlease note that the above list does not reflect requirements for:\n\n- Additional components in this distribution, see `lib/`. Additional\ncomponents list own requirements\n- Test and build system, please see: `Build.PL` for details\n- Requirements for scripts in the `bin/` directory\n- Requirements for examples in the `examples/` directory\n\n# BUGS AND LIMITATIONS\n\nThere are no known bugs at this time.\n\nThe data source used in this distribution by no means is authorative when it\ncomes to cities located in Denmark, it might have all cities listed, but\nunfortunately also other post distribution data.\n\n# BUG REPORTING\n\nPlease report issues via CPAN RT:\n\n- Web (RT): [http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-DK-Postalcode](http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-DK-Postalcode)\n- Web (Github): [https://github.com/jonasbn/bdkpst/issues](https://github.com/jonasbn/bdkpst/issues)\n- Email (RT): [bug-Business-DK-Postalcode@rt.cpan.org](https://metacpan.org/pod/bug-Business-DK-Postalcode@rt.cpan.org)\n\n# INCOMPATIBILITIES\n\nThere are no known incompatibilities at this time.\n\n# TEST AND QUALITY\n\n## Perl::Critic\n\nThis version of the code is complying with [https://metacpan.org/pod/Perl::Critic](https://metacpan.org/pod/Perl::Critic) a severity: 1\n\nThe following policies have been disabled.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::Variables::ProhibitPackageVars](https://metacpan.org/pod/Perl::Critic::Policy::Variables::ProhibitPackageVars)\n\n    Disabled locally using 'no critic' pragma.\n\n    The module  uses a package variable as a cache, this might not prove usefull in\n    the long term, so when this is adressed and this might address this policy.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::Subroutines::RequireArgUnpacking](https://metacpan.org/pod/Perl::Critic::Policy::Subroutines::RequireArgUnpacking)\n\n    Disabled locally using 'no critic' pragma.\n\n    This policy is violated when using [https://metacpan.org/pod/Params::Validate](https://metacpan.org/pod/Params::Validate) at some point this will\n    be investigated further, this might be an issue due to referral to @\\_.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching](https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireLineBoundaryMatching)\n\n    Disabled locally using 'no critic' pragma.\n\n    This is disabled for some two basic regular expressions.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting](https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireExtendedFormatting)\n\n    Disabled locally using 'no critic' pragma.\n\n    This is disabled for some two basic regular expressions.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything](https://metacpan.org/pod/Perl::Critic::Policy::RegularExpressions::RequireDotMatchAnything)\n\n    Disabled locally using 'no critic' pragma.\n\n    This is disabled for some two basic regular expressions.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma](https://metacpan.org/pod/Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma)\n\n    Constants are good, - see the link below.\n\n- [https://logiclab.jira.com/wiki/display/OPEN/Perl-Critic-Policy-ValuesAndExpressions-ProhibitConstantPragma](https://logiclab.jira.com/wiki/display/OPEN/Perl-Critic-Policy-ValuesAndExpressions-ProhibitConstantPragma)\n- [https://metacpan.org/pod/Perl::Critic::Policy::Documentation::RequirePodAtEnd](https://metacpan.org/pod/Perl::Critic::Policy::Documentation::RequirePodAtEnd)\n\n    This one interfers with our DATA section, perhaps DATA should go before POD,\n    well it is not important so I have disabled the policy.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops](https://metacpan.org/pod/Perl::Critic::Policy::ControlStructures::ProhibitCStyleForLoops)\n\n    This would require a re-write of part of the code. Currently I rely on use of the iterator in the `for` loop, so it would require significant\n    changes.\n\n- [https://metacpan.org/pod/Perl::Critic::Policy::Documentation::RequirePodLinksIncludeText](https://metacpan.org/pod/Perl::Critic::Policy::Documentation::RequirePodLinksIncludeText)\n\n    Temporarily disabled, marked for follow-up\n\nPlease see `t/perlcriticrc` for details.\n\n## TEST COVERAGE\n\nTest coverage report is generated using [https://metacpan.org/pod/Devel::Cover](https://metacpan.org/pod/Devel::Cover) via [https://metacpan.org/pod/Module::Build](https://metacpan.org/pod/Module::Build),\nfor the version described in this documentation (See [VERSION](https://metacpan.org/pod/VERSION)).\n\n    ---------------------------- ------ ------ ------ ------ ------ ------ ------\n    File                           stmt   bran   cond    sub    pod   time  total\n    ---------------------------- ------ ------ ------ ------ ------ ------ ------\n    ...Business/DK/Postalcode.pm  100.0  100.0    n/a  100.0  100.0   98.7  100.0\n    ...Business/DK/Postalcode.pm  100.0  100.0    n/a  100.0  100.0    1.2  100.0\n    Total                         100.0  100.0    n/a  100.0  100.0  100.0  100.0\n    ---------------------------- ------ ------ ------ ------ ------ ------ ------\n\n    $ ./Build testcover\n\n# SEE ALSO\n\n- Main data source: [http://www.postdanmark.dk/da/Documents/Lister/postnummerfil-excel.xls](http://www.postdanmark.dk/da/Documents/Lister/postnummerfil-excel.xls)\n- Information resource on data source: [http://www.postdanmark.dk/cms/da-dk/eposthuset/postservices/aendringer\\_postnumre\\_1.htm](http://www.postdanmark.dk/cms/da-dk/eposthuset/postservices/aendringer_postnumre_1.htm)\n- Alternative implementation: [https://metacpan.org/pod/Geo::Postcodes::DK](https://metacpan.org/pod/Geo::Postcodes::DK)\n- Alternative validation: [https://metacpan.org/module/Regexp::Common::zip#RE-zip-Denmark-](https://metacpan.org/module/Regexp::Common::zip#RE-zip-Denmark-)\n- Related complementary implementation: [https://metacpan.org/pod/Business::GL::Postalcode](https://metacpan.org/pod/Business::GL::Postalcode)\n- Related complementary implementation: [https://metacpan.org/pod/Business::FO::Postalcode](https://metacpan.org/pod/Business::FO::Postalcode)\n- Related implementation, same author: [https://metacpan.org/pod/Business::DK::CVR](https://metacpan.org/pod/Business::DK::CVR)\n- Related implementation, same author: [https://metacpan.org/pod/Business::DK::CPR](https://metacpan.org/pod/Business::DK::CPR)\n- Related implementation, same author: [https://metacpan.org/pod/Business::DK::FI](https://metacpan.org/pod/Business::DK::FI)\n- Related implementation, same author: [https://metacpan.org/pod/Business::DK::PO](https://metacpan.org/pod/Business::DK::PO)\n\n# RESOURCES\n\n- MetaCPAN: [https://metacpan.org/pod/Business::DK::Postalcode](https://metacpan.org/pod/Business::DK::Postalcode)\n- Website: [http://logicLAB.jira.com/browse/BDKPST](http://logicLAB.jira.com/browse/BDKPST)\n- Bugtracker: [http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-DK-Postalcode](http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-DK-Postalcode)\n- Git repository: [https://github.com/jonasbn/bdkpst](https://github.com/jonasbn/bdkpst)\n\n# TODO\n\nPlease see the project `TODO` file, or the bugtracker (RT), website or issues resource at Github.\n\n# AUTHOR\n\n- Jonas B. Nielsen, (jonasbn) - `\u003cjonasbn@cpan.org\u003e`\n\n# ACKNOWLEDGEMENTS\n\n- Mohammad S Anwar, POD corrections PR #6\n\n# MOTIVATION\n\nBack in 2006 I was working on a project where I needed to do some presentation\nand validation of Danish postal codes. I looked at [https://metacpan.org/pod/Regex::Common::Zip](https://metacpan.org/pod/Regex::Common::Zip)\n\nThe implementation at the time of writing looked as follows:\n\n    Denmark     =\u003e  \"(?k:(?k:[1-9])(?k:[0-9])(?k:[0-9]{2}))\",\n    # Postal codes of the form: 'DDDD', with the first\n    # digit representing the distribution region, the\n    # second digit the distribution district. Postal\n    # codes do not start with a zero. Postal codes\n    # starting with '39' are in Greenland.\n\nThis pattern holds some issues:\n\n- Doing some fast math you can see that you will allow 9000 valid postal\ncodes where the number should be about 1254\n- 0 is actually allowed for a set of postal codes used by the postal service\nin Denmark, in some situations these should perhaps be allowed as valid data\n- Greenland specified as starting with '39' is not a part of Denmark, but\nshould be under Greenland and the ISO code 'GL', see also:\n    - [https://metacpan.org/pod/Business::GL::Postalcode](https://metacpan.org/pod/Business::GL::Postalcode)\n\nSo I decided to write a regular expression, which would be better than the one\nabove, but I did not want to maintain it I wanted to write a piece of software,\nwhich could generate the pattern for me based on a finite data set.\n\n# COPYRIGHT\n\nBusiness-DK-Postalcode is (C) by Jonas B. Nielsen, (jonasbn) 2006-2019\n\n# LICENSE\n\nBusiness-DK-Postalcode and related is released under the Artistic License 2.0\n\n- [http://www.opensource.org/licenses/Artistic-2.0](http://www.opensource.org/licenses/Artistic-2.0)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonasbn%2Fbdkpst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonasbn%2Fbdkpst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonasbn%2Fbdkpst/lists"}