postcode_checker

A comprehensive Dart package for validating postal codes from countries worldwide using ISO 3166-1 alpha-2 country codes and CLDR-based regex patterns.

Pub Version Pub Points Pub Likes License: MIT

CI codecov

Features

  • โœ… Comprehensive Coverage: Supports 170+ countries and territories
  • ๐ŸŒ ISO 3166-1 Standard: Uses official alpha-2 country codes
  • ๐ŸŽฏ CLDR-Based Patterns: Regex patterns from Unicode CLDR v26.0.1
  • ๐Ÿ” Simple Static API: Clean, no-instantiation design
  • ๐Ÿšจ Type-Safe Error Handling: Enum-based error types with clear messages
  • ๐Ÿ“ฆ Zero Dependencies: No external dependencies required
  • ๐Ÿงช Well Tested: Comprehensive unit test coverage
  • ๐Ÿ“š Well Documented: Clear examples and API documentation

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  postcode_checker: ^1.0.2

Then run:

dart pub get

Usage

Basic Validation

import 'package:postcode_checker/postcode_checker.dart';

void main() {
  // Validate a US ZIP code
  final usResult = PostcodeChecker.validate(CountryCode.US, '12345');
  print(usResult.isValid); // true

  // Validate a UK postcode
  final ukResult = PostcodeChecker.validate(CountryCode.GB, 'SW1A 1AA');
  print(ukResult.isValid); // true

  // Validate an invalid postal code
  final invalidResult = PostcodeChecker.validate(CountryCode.US, 'INVALID');
  print(invalidResult.isValid); // false
  print(invalidResult.errorMessage); // Error description
}

Working with Validation Results

final result = PostcodeChecker.validate(CountryCode.CA, 'K1A 0B1');

if (result.isValid) {
  print('Valid postal code for ${result.countryCode.code}');
} else {
  print('Invalid: ${result.errorMessage}');
}

Error Handling

The package provides type-safe error handling with clear error messages:

// Empty postal code error
final emptyResult = PostcodeChecker.validate(CountryCode.US, '');
print(emptyResult.error); // PostcodeValidationError.emptyPostalCode
print(emptyResult.errorCode); // 'EMPTY_POSTAL_CODE'
print(emptyResult.errorMessage); // 'Postal code cannot be empty or contain only whitespace.'

// Invalid format error
final invalidResult = PostcodeChecker.validate(CountryCode.US, 'ABC');
print(invalidResult.error); // PostcodeValidationError.invalidFormat
print(invalidResult.errorCode); // 'INVALID_FORMAT'
print(invalidResult.errorMessage); // 'The postal code does not match the expected format for this country.'

// No postal code system error
final noSystemResult = PostcodeChecker.validate(CountryCode.AO, '12345');
print(noSystemResult.error); // PostcodeValidationError.noPostalCodeSystem
print(noSystemResult.errorCode); // 'NO_POSTAL_CODE_SYSTEM'

Available error types:

  • PostcodeValidationError.emptyPostalCode - Empty or whitespace-only input
  • PostcodeValidationError.invalidFormat - Postal code doesn't match country pattern
  • PostcodeValidationError.noPostalCodeSystem - Country doesn't use postal codes
  • PostcodeValidationError.unsupportedCountry - Country code not recognized

Check if a Country Has Postal Codes

print(PostcodeChecker.hasPostalCodes(CountryCode.US)); // true
print(PostcodeChecker.hasPostalCodes(CountryCode.GB)); // true
print(PostcodeChecker.hasPostalCodes(CountryCode.AO)); // false (Angola has no postal codes)

Get Postal Code Pattern

final pattern = PostcodeChecker.getPostalCodePattern(CountryCode.US);
print(pattern); // \d{5}([ \-]\d{4})?

final caPattern = PostcodeChecker.getPostalCodePattern(CountryCode.CA);
print(caPattern); // [ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d

List Supported Countries

final countries = PostcodeChecker.supportedCountries();
print('Supported countries: ${countries.length}');

for (final country in countries.take(5)) {
  print(country.code);
}

Supported Countries

This package supports postal code validation for 170+ countries and territories, including:

North America

  • ๐Ÿ‡บ๐Ÿ‡ธ United States (US)
  • ๐Ÿ‡จ๐Ÿ‡ฆ Canada (CA)
  • ๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico (MX)
  • ๐Ÿ‡ต๐Ÿ‡ท Puerto Rico (PR)

Europe

  • ๐Ÿ‡ฌ๐Ÿ‡ง United Kingdom (GB)
  • ๐Ÿ‡ฉ๐Ÿ‡ช Germany (DE)
  • ๐Ÿ‡ซ๐Ÿ‡ท France (FR)
  • ๐Ÿ‡ฎ๐Ÿ‡น Italy (IT)
  • ๐Ÿ‡ช๐Ÿ‡ธ Spain (ES)
  • ๐Ÿ‡ณ๐Ÿ‡ฑ Netherlands (NL)
  • ๐Ÿ‡ต๐Ÿ‡ฑ Poland (PL)
  • ๐Ÿ‡ธ๐Ÿ‡ช Sweden (SE)
  • And many more...

Asia-Pacific

  • ๐Ÿ‡ฏ๐Ÿ‡ต Japan (JP)
  • ๐Ÿ‡จ๐Ÿ‡ณ China (CN)
  • ๐Ÿ‡ฎ๐Ÿ‡ณ India (IN)
  • ๐Ÿ‡ฆ๐Ÿ‡บ Australia (AU)
  • ๐Ÿ‡ธ๐Ÿ‡ฌ Singapore (SG)
  • ๐Ÿ‡ฐ๐Ÿ‡ท South Korea (KR)
  • And many more...

South America

  • ๐Ÿ‡ง๐Ÿ‡ท Brazil (BR)
  • ๐Ÿ‡ฆ๐Ÿ‡ท Argentina (AR)
  • ๐Ÿ‡จ๐Ÿ‡ฑ Chile (CL)
  • ๐Ÿ‡จ๐Ÿ‡ด Colombia (CO)
  • And more...

Africa & Middle East

  • ๐Ÿ‡ฟ๐Ÿ‡ฆ South Africa (ZA)
  • ๐Ÿ‡ช๐Ÿ‡ฌ Egypt (EG)
  • ๐Ÿ‡ฎ๐Ÿ‡ฑ Israel (IL)
  • ๐Ÿ‡น๐Ÿ‡ท Turkey (TR)
  • ๐Ÿ‡ธ๐Ÿ‡ฆ Saudi Arabia (SA)
  • And more...

See the full list of supported countries or use PostcodeChecker.supportedCountries() to get a complete list.

Examples

Validate Multiple Countries

final testCases = {
  CountryCode.US: ['12345', '12345-6789', 'INVALID'],
  CountryCode.GB: ['SW1A 1AA', 'M1 1AA', '12345'],
  CountryCode.DE: ['10115', '80331', '1234'],
  CountryCode.JP: ['100-0001', '060-0001', '1000001'],
};

for (final entry in testCases.entries) {
  final country = entry.key;
  final codes = entry.value;

  print('Testing ${country.code}:');
  for (final code in codes) {
    final result = PostcodeChecker.validate(country, code);
    print('  ${code}: ${result.isValid}');
  }
}

Custom Validation Function

bool isValidPostalCode(String countryCode, String postalCode) {
  // Parse country code string to enum
  final country = CountryCode.values.firstWhere(
    (c) => c.code == countryCode.toUpperCase(),
    orElse: () => throw ArgumentError('Invalid country code: $countryCode'),
  );

  return PostcodeChecker.validate(country, postalCode).isValid;
}

// Usage
print(isValidPostalCode('US', '12345')); // true
print(isValidPostalCode('GB', 'SW1A 1AA')); // true

API Reference

PostcodeChecker

The main class for validating postal codes.

Methods

  • validate(CountryCode countryCode, String postalCode): Validates a postal code for the specified country. Returns a PostcodeValidationResult.

  • getPostalCodePattern(CountryCode countryCode): Returns the regex pattern for the specified country, or null if not available.

  • hasPostalCodes(CountryCode countryCode): Returns true if the country has a postal code system.

  • supportedCountries(): Returns a list of all countries with postal code validation support.

PostcodeValidationResult

Represents the result of a postal code validation.

Properties

  • isValid: Whether the postal code is valid.
  • countryCode: The country code used for validation.
  • postalCode: The postal code that was validated.
  • errorMessage: Optional error message if validation failed.

Factory Methods

  • PostcodeValidationResult.valid(CountryCode, String): Creates a successful validation result.
  • PostcodeValidationResult.invalid(CountryCode, String, String): Creates a failed validation result.

CountryCode

Enum representing ISO 3166-1 alpha-2 country codes.

Extension Methods

  • code: Returns the two-letter country code as a string.

Data Source

The postal code validation patterns in this package are based on the Unicode CLDR (Common Locale Data Repository) version 26.0.1, which was the last version to include postal code data before it was deprecated in 2016.

CLDR was chosen as the primary data source because:

  • โœ… Maintained by the Unicode Consortium
  • โœ… Widely used and tested
  • โœ… Comprehensive coverage of 170+ territories
  • โœ… Well-documented regex patterns

For countries not covered by CLDR, patterns may be sourced from other reliable sources such as government postal services or international standards organizations.

Pattern Format

All postal code patterns support:

  • Optional spacing: Many patterns allow optional spaces (e.g., SW1A 1AA or SW1A1AA)
  • Optional separators: Hyphens and spaces where commonly used (e.g., 12345-6789)
  • Case insensitivity: Patterns work with both uppercase and lowercase letters
  • Strict validation: Only validates the format, not whether the code actually exists

Contributing

Contributions are welcome! If you find a bug or want to add support for additional countries, please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Adding a New Country Pattern

To add support for a new country:

  1. Add the pattern to the switch statement in lib/src/postcode_checker.dart
  2. Add comprehensive tests in test/postcode_checker_test.dart
  3. Update the documentation

Testing

Run the test suite:

dart test

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Unicode CLDR: For providing comprehensive postal code patterns
  • ISO 3166: For the international standard of country codes
  • All contributors who help improve this package

Support

If you find this package helpful, please:

  • โญ Star the repository on GitHub
  • ๐Ÿ› Report issues on the issue tracker
  • ๐Ÿ“ Contribute improvements via pull requests

Versioning

This package follows Semantic Versioning:

  • MAJOR version for incompatible API changes
  • MINOR version for backwards-compatible functionality additions
  • PATCH version for backwards-compatible bug fixes

Current version: 1.0.2


Made with โค๏ธ by the postcode_checker team

Libraries

postcode_checker
A comprehensive Dart package for validating postal codes from countries worldwide using ISO 3166-1 alpha-2 country codes.