Index: django/contrib/localflavor/nz/__init__.py
===================================================================
Index: django/contrib/localflavor/nz/nz_provincial_districts.py
===================================================================
--- django/contrib/localflavor/nz/nz_provincial_districts.py	(revision 0)
+++ django/contrib/localflavor/nz/nz_provincial_districts.py	(revision 0)
@@ -0,0 +1,18 @@
+from django.utils.translation import gettext_lazy as _
+
+PROVINCIAL_DISTRICT_CHOICES = (
+    ('Auckland', _('Auckland Province')),
+    ('Canterbury', _('Canterbury')),
+    ('Chatham', _('Chatham Islands')),
+    ('HawkesBay', _("Hawke's Bay")),
+    ('Marlborough', _('Marlborough')),
+    ('Nelson', _('Nelson')),
+    ('Northland', _('Northland')),
+    ('Otago', _('Otago Province')),
+    ('SouthCanterbury', _('South Canterbury')),
+    ('Southland', _('Southland')),
+    ('Taranaki', _('Taranaki (New Plymouth)')),
+    ('Wellington', _('Wellington Province')),
+    ('Westland', _('Westland')),
+
+)
Index: django/contrib/localflavor/nz/forms.py
===================================================================
--- django/contrib/localflavor/nz/forms.py	(revision 0)
+++ django/contrib/localflavor/nz/forms.py	(revision 0)
@@ -0,0 +1,51 @@
+"""
+New Zealand-specific Form helpers
+"""
+
+from django.core.validators import EMPTY_VALUES
+from django.forms import ValidationError
+from django.forms.fields import Field, RegexField, Select
+from django.utils.encoding import smart_unicode
+from django.utils.translation import ugettext_lazy as _
+import re
+
+PHONE_DIGITS_RE = re.compile(r'^((0\d{8})|(02\d{7,9}))$')
+
+class NZPostCodeField(RegexField):
+    """New Zealand post code field."""
+    default_error_messages = {
+        'invalid': _('Enter a 4 digit post code.'),
+    }
+
+    def __init__(self, *args, **kwargs):
+        super(NZPostCodeField, self).__init__(r'^\d{4}$',
+            max_length=None, min_length=None, *args, **kwargs)
+
+class NZPhoneNumberField(Field):
+    """New Zealand phone number field."""
+    default_error_messages = {
+        'invalid': u'Phone numbers must contain 9 digits (including area code),'
+        ' unless they are mobile numbers (02, then 7-9 digits).',
+    }
+
+    def clean(self, value):
+        """
+        Validate a phone number. Strips parentheses, whitespace and hyphens.
+        """
+        super(NZPhoneNumberField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+        value = re.sub('(\(|\)|\s+|-)', '', smart_unicode(value))
+        phone_match = PHONE_DIGITS_RE.search(value)
+        if phone_match:
+            return u'%s' % phone_match.group(1)
+        raise ValidationError(self.error_messages['invalid'])
+
+class NZProvincialDistrictSelect(Select):
+    """
+    A Select widget that uses a list of Australian states/territories as its
+    choices.
+    """
+    def __init__(self, attrs=None):
+        from nz_provincial_districts import PROVINCIAL_DISTRICT_CHOICES
+        super(NZProvincialDistrictSelect, self).__init__(attrs, choices=PROVINCIAL_DISTRICT_CHOICES)
Index: tests/regressiontests/forms/localflavor/nz.py
===================================================================
--- tests/regressiontests/forms/localflavor/nz.py	(revision 0)
+++ tests/regressiontests/forms/localflavor/nz.py	(revision 0)
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+# Tests for the contrib/localflavor/ NZ form fields.
+
+tests = r"""
+## NZPostCodeField ##########################################################
+
+A field that accepts a four digit New Zealand post code.
+
+>>> from django.contrib.localflavor.nz.forms import NZPostCodeField
+>>> f = NZPostCodeField()
+>>> f.clean('1234')
+u'1234'
+>>> f.clean('2000')
+u'2000'
+>>> f.clean('abcd')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a 4 digit post code.']
+>>> f.clean('20001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a 4 digit post code.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = NZPostCodeField(required=False)
+>>> f.clean('1234')
+u'1234'
+>>> f.clean('2000')
+u'2000'
+>>> f.clean('abcd')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a 4 digit post code.']
+>>> f.clean('20001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a 4 digit post code.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+## NZPhoneNumberField ########################################################
+
+A field that accepts a 9 digit New Zealand phone number, or a 8-10 digit
+New Zealand mobile phone number (starting with 02).
+Allows spaces and parentheses around area code.
+
+>>> from django.contrib.localflavor.nz.forms import NZPhoneNumberField
+>>> f = NZPhoneNumberField()
+>>> f.clean('012345678')
+u'012345678'
+>>> f.clean('0213456789')
+u'0213456789'
+>>> f.clean('02 13 45 67 8')
+u'021345678'
+>>> f.clean('(02) 1345 6789')
+u'0213456789'
+>>> f.clean('(02) 1345-6789')
+u'0213456789'
+>>> f.clean('(02)1345-6789')
+u'0213456789'
+>>> f.clean('0228 123 45')
+u'022812345'
+>>> f.clean('123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+>>> f.clean('1800DJANGO')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = NZPhoneNumberField(required=False)
+>>> f.clean('1234567890')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+>>> f.clean('0213456789')
+u'0213456789'
+>>> f.clean('02 13 45 67 89')
+u'0213456789'
+>>> f.clean('(02) 1345 6789')
+u'0213456789'
+>>> f.clean('(02) 1345-6789')
+u'0213456789'
+>>> f.clean('(02)1345-6789')
+u'0213456789'
+>>> f.clean('0408 123 456')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+
+>>> f.clean('123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+>>> f.clean('1800DJANGO')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must contain 9 digits (including area code), unless they are mobile numbers (02, then 7-9 digits).']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+
+## NZStateSelect #############################################################
+
+NZProvincialDistrictSelect is a Select widget that uses a list of New Zealand
+provincial districts as its choices.
+
+>>> from django.contrib.localflavor.nz.forms import NZProvincialDistrictSelect
+>>> f = NZProvincialDistrictSelect()
+>>> print f.render('provincial_district', 'Wellington')
+<select name="provincial_district">
+<option value="Auckland">Auckland Province</option>
+<option value="Canterbury">Canterbury</option>
+<option value="Chatham">Chatham Islands</option>
+<option value="HawkesBay">Hawke's Bay</option>
+<option value="Marlborough">Marlborough</option>
+<option value="Nelson">Nelson</option>
+<option value="Northland">Northland</option>
+<option value="Otago">Otago Province</option>
+<option value="SouthCanterbury">South Canterbury</option>
+<option value="Southland">Southland</option>
+<option value="Taranaki">Taranaki (New Plymouth)</option>
+<option value="Wellington" selected="selected">Wellington Province</option>
+<option value="Westland">Westland</option>
+</select>
+
+"""
\ No newline at end of file
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 13336)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -22,6 +22,7 @@
 from localflavor.jp import tests as localflavor_jp_tests
 from localflavor.kw import tests as localflavor_kw_tests
 from localflavor.nl import tests as localflavor_nl_tests
+from localflavor.nz import tests as localflavor_nz_tests
 from localflavor.pl import tests as localflavor_pl_tests
 from localflavor.pt import tests as localflavor_pt_tests
 from localflavor.ro import tests as localflavor_ro_tests
@@ -65,6 +66,7 @@
     'localflavor_jp_tests': localflavor_jp_tests,
     'localflavor_kw_tests': localflavor_kw_tests,
     'localflavor_nl_tests': localflavor_nl_tests,
+    'localflavor_nz_tests': localflavor_nz_tests,
     'localflavor_pl_tests': localflavor_pl_tests,
     'localflavor_pt_tests': localflavor_pt_tests,
     'localflavor_ro_tests': localflavor_ro_tests,
