diff --git a/django/contrib/localflavor/sg/__init__.py b/django/contrib/localflavor/sg/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/django/contrib/localflavor/sg/forms.py b/django/contrib/localflavor/sg/forms.py
new file mode 100644
index 0000000..5858506
--- /dev/null
+++ b/django/contrib/localflavor/sg/forms.py
@@ -0,0 +1,146 @@
+
+"""
+SG-specific Form helpers
+"""
+
+from __future__ import absolute_import
+
+import re
+import time
+
+from django.core.validators import EMPTY_VALUES
+from django.forms import ValidationError
+from django.core.validators import RegexValidator
+from django.forms.fields import Field, Select
+from django.utils.translation import ugettext_lazy as _
+from django.utils.encoding import smart_unicode
+
+# from http://www.ura.gov.sg/realEstateWeb/resources/misc/list_of_postal_districts.htm
+postcode_re = re.compile(r'^(?!(83|84|85|86|87|88|89))([0-8][0-9])\d{4}$')
+# RE for both NRIC and FIN.  Check sum and validity of the numerical part
+# are not calculated, due to branching rules and b/c the checksum isn't
+# in the public domain.
+# Format : @0000000#
+# @ is centry marker, S,T for NRIC, F,G for FIN
+# 0000000 is the serial no, with aditional constraints for birth year.
+# # is Checksum.
+nric_re = re.compile(r'([sftg])\d{7}[a-z]$',re.IGNORECASE)
+mobile_phone_re = re.compile(r'^[(]?(?P<cc>\+65)[)]?(?P<num>[89]\d{7})')
+phone_re = re.compile(r'^[(]?(?P<cc>\+65)[)]?(?P<num>[3689]\d{7})')
+
+class NRICValidator(RegexValidator):
+    code = 'invalid'
+    message = _('Enter a valid NRIC/FIN number')
+    regex = nric_re
+
+    def __call__(self,value):
+        super(NRICValidator,self).__call__(value)
+
+validate_nric = NRICValidator()
+
+class SGPhoneValidator(RegexValidator):
+    code = 'invalid'
+    message = _('Enter a valid phone number'),
+    regex = phone_re
+
+    def __call__(self,value):
+        super(SGPhoneValidator,self).__call__(value)
+
+validate_SG_phone = SGPhoneValidator()
+validate_SG_mobile_phone = SGPhoneValidator(regex=mobile_phone_re)
+
+class SGPostCodeValidator(RegexValidator):
+    code = 'invalid'
+    message = _('Enter a valid post code'),
+    regex = postcode_re
+
+    def __call__(self,value):
+        super(SGPostCodeValidator,self).__call__(value)
+
+validate_SG_postcode = SGPostCodeValidator()
+
+class SGPostCodeField(Field):
+    """
+    A Singaporian post code field.
+
+    http://www.ura.gov.sg/realEstateWeb/resources/misc/list_of_postal_districts.htm
+    """
+    default_error_messages = {
+            'invalid': _('Enter a valid post code'),
+            'required': _('Post code is required'),
+            }
+    default_validators = [validate_SG_postcode]
+
+    def validate(self, value):
+        if value in EMPTY_VALUES and self.required:
+            raise ValidationError(self.error_messages['required'])
+
+    def to_python(self,value):
+        if not value:
+            return u''
+        return value.strip()
+
+    def clean(self,value):
+        value = self.to_python(value)
+        self.validate(value)
+        self.run_validators(value)
+        return value
+
+class SGPhoneNumberField(Field):
+    """
+    Singaporian phone number field.
+
+    http://en.wikipedia.org/wiki/Telephone_numbers_in_Singapore
+    """
+    default_error_messages = {
+            'invalid': _('Enter a valid phone number'),
+            }
+
+    def __init__(self, mobile_phone_only=False, *args, **kwargs):
+        if mobile_phone_only:
+            validators = [validate_SG_mobile_phone,]
+        else:
+            validators = [validate_SG_phone,]
+        super(SGPhoneNumberField, self).__init__(validators=validators, *args,
+                **kwargs)
+
+    def to_python(self,value):
+        if not value:
+            return u''
+        return value.strip()
+
+    def clean(self,value):
+        value = self.to_python(value)
+        self.validate(value)
+        self.run_validators(value)
+        v_search = phone_re.search(value)
+        if value in EMPTY_VALUES and not self.required:
+            return value
+        elif not v_search:
+            raise ValidationError(self.default_error_messages['invalid'])
+
+        return u"{0}{1}".format(v_search.group('cc'),
+                                v_search.group('num'))
+
+class SGNationalRegistrationIdentityCard(Field):
+    """
+    Singaporian NRIC and FIN card
+
+    http://http://en.wikipedia.org/wiki/National_Registration_Identity_Card
+    """
+    default_error_messages = {
+            'invalid': _('Enter a valid NRIC/FIN number'),
+            'required': _('NRIC/FIN is required'),
+                }
+    default_validators = [RegexValidator(nric_re,code='invalid')]
+
+    def to_python(self,value):
+        if not value:
+            return u''
+        return value.strip()
+
+    def clean(self,value):
+        """Validates NRIC/FIN number, cleans, etc.
+        raises ValidationError on any error"""
+        value = super(SGNationalRegistrationIdentityCard, self).clean(value)
+        return value.upper()
diff --git a/tests/regressiontests/generic_views/.edit.py.swp b/tests/regressiontests/generic_views/.edit.py.swp
new file mode 100644
index 0000000..a498a68
Binary files /dev/null and b/tests/regressiontests/generic_views/.edit.py.swp differ
diff --git a/tests/regressiontests/localflavor/sg/__init__.py b/tests/regressiontests/localflavor/sg/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/regressiontests/localflavor/sg/tests.py b/tests/regressiontests/localflavor/sg/tests.py
new file mode 100644
index 0000000..1f77cb8
--- /dev/null
+++ b/tests/regressiontests/localflavor/sg/tests.py
@@ -0,0 +1,70 @@
+import warnings
+
+from django.contrib.localflavor.sg.forms import (SGPhoneNumberField,
+        SGPostCodeField, SGNationalRegistrationIdentityCard)
+
+from django.test import SimpleTestCase
+
+class SGLocalFlavorTests(SimpleTestCase):
+    """Test the form"""
+    def test_phone(self):
+        error_invalid = [u'Enter a valid phone number']
+        valid = {
+                '+6594761111':'+6594761111',
+                '(+65)94761111':'+6594761111',
+                '+6565521111':'+6565521111',
+                }
+        invalid = {
+                '94761111':error_invalid,
+                '(+65)44761111':error_invalid,
+                '+6365521111':error_invalid,
+                }
+        self.assertFieldOutput(SGPhoneNumberField, valid, invalid)
+
+    def test_mobile(self):
+        error_invalid = [u'Enter a valid phone number']
+        valid = {
+                '+6594761111':'+6594761111',
+                '(+65)94761111':'+6594761111',
+                '+6585521111':'+6585521111',
+        }
+        invalid = {
+                '94761111':error_invalid,
+                '(+65)44761111':error_invalid,
+                '+6365521111':error_invalid,
+                '+6565521111':error_invalid,
+                }
+        self.assertFieldOutput(SGPhoneNumberField, valid, invalid,
+                field_kwargs={'mobile_phone_only':True,})
+
+    def test_postcode(self):
+        error_invalid = [u'Enter a valid post code']
+        error_required = [u'Post code is required']
+        valid = {
+                '570248':'570248',
+                '010001':'010001',
+                '580222':'580222',
+                }
+        invalid = {
+                '852222':error_invalid,
+                'm5d-2g4':error_invalid,
+                '123':error_invalid,
+                }
+        self.assertFieldOutput(SGPostCodeField, valid, invalid,
+                field_kwargs={'required':True})
+
+    def test_NRIC_num(self):
+        error_invalid = [u'Enter a valid NRIC/FIN number']
+        valid = {
+                'S0850356G':'S0850356G',
+                'T0850356C':'T0850356C',
+                'F8554629P':'F8554629P',
+                'G0854629R':'G0854629R',
+                'g0854629R':'G0854629R',
+                }
+        invalid= {
+                'S0123F':error_invalid,
+                'R0850356G':error_invalid,
+                'F8554629PP':error_invalid,
+                }
+        self.assertFieldOutput(SGNationalRegistrationIdentityCard, valid, invalid)
diff --git a/tests/regressiontests/localflavor/tests.py b/tests/regressiontests/localflavor/tests.py
index 856e518..bab4b0f 100644
--- a/tests/regressiontests/localflavor/tests.py
+++ b/tests/regressiontests/localflavor/tests.py
@@ -37,6 +37,7 @@ from .py.tests import PYLocalFlavorTests
 from .ro.tests import ROLocalFlavorTests
 from .ru.tests import RULocalFlavorTests
 from .se.tests import SELocalFlavorTests
+from .sg.tests import SGLocalFlavorTests
 from .si.tests import SILocalFlavorTests
 from .sk.tests import SKLocalFlavorTests
 from .tr.tests import TRLocalFlavorTests
