Index: django/contrib/localflavor/lv/__init__.py
===================================================================
Index: django/contrib/localflavor/lv/models.py
===================================================================
--- django/contrib/localflavor/lv/models.py	(revision 0)
+++ django/contrib/localflavor/lv/models.py	(revision 0)
@@ -0,0 +1 @@
+# needed for some testing, see ticket #7198
Index: django/contrib/localflavor/lv/forms.py
===================================================================
--- django/contrib/localflavor/lv/forms.py	(revision 0)
+++ django/contrib/localflavor/lv/forms.py	(revision 0)
@@ -0,0 +1,62 @@
+# encoding: utf-8
+import time 
+import re
+
+from django.forms import ValidationError
+from django.forms.fields import CharField, RegexField
+from django.utils.translation import ugettext_lazy as _
+
+identity_number_digits_re = re.compile(r'^(\d{11})$')
+
+class LVPhoneField(RegexField):
+    
+    default_error_messages = {
+        'invalid': _('Phone numbers must be in XXXXXXXX format.'),
+    }
+    def __init__(self, *args, **kwargs):
+        super(LVPhoneField, self).__init__(r'^(\d{8})$',
+            max_length=None, min_length=None, *args, **kwargs)
+
+class LVPostalCodeField(RegexField):
+    default_error_messages = {
+        'invalid' : _('Postal code fields must be in LV-XXXX format')
+    }
+    def __init__(self, *args, **kwargs):
+        super(LVPostalCodeField, self).__init__(r'LV-(\d{4})$',
+                max_length = None, min_length = None, *args, **kwargs)
+
+class LVIdentityNumberField(CharField):
+    """ 
+        Latvian identity number field.
+        Checks following rules that number is valid:
+        - first 6 digits form valid date
+        - conforms form XXXXXX-XXXXX
+        - last digit is valid checksum 
+            algorithm for validation 
+            (1101 – (1*PK[1] + 6*PK[2] + 3*PK[3] + 7*PK[4] + 9*PK[5] + 10*PK[6] + 5*PK[7] + 8*PK[8] + 4*PK[9] + 2*PK[10])) mod 11
+    """
+    default_error_messages = {
+        'invalid':  _('Identity numbers must be in XXXXXX-XXXXX format')
+    }
+    def clean(self, value):
+        super(LVIdentityNumberField, self).clean(value)
+        date = value[:6]
+        meta = value[7:]
+        value = date+ meta
+        if not identity_number_digits_re.match(value):
+            raise ValidationError(self.error_messages['invalid'])
+        try:
+            time.strptime(date, "%d%m%y")
+        except ValueError:
+            raise ValidationError(self.error_messages['invalid'])
+        def calculate_checksum(code):
+            """ common knownledge algorithm for calculating identity number checksum """
+            checksum = 0
+            validation_data = [1,6,3,7,9,10,5,8,4,2]
+            for i in xrange(0, 10):
+                checksum += int(code[i]) * validation_data[i]
+            checksum =  (1101 - checksum) % 11
+            return checksum
+        if calculate_checksum(value) != int(value[10]):
+            raise ValidationError(self.error_messages['invalid'])
+        return value
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 13984)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -31,6 +31,7 @@
 from localflavor.us import tests as localflavor_us_tests
 from localflavor.uy import tests as localflavor_uy_tests
 from localflavor.za import tests as localflavor_za_tests
+from localflavor.lv import * 
 from regressions import tests as regression_tests
 from util import tests as util_tests
 from widgets import tests as widgets_tests
Index: tests/regressiontests/forms/localflavor/lv.py
===================================================================
--- tests/regressiontests/forms/localflavor/lv.py	(revision 0)
+++ tests/regressiontests/forms/localflavor/lv.py	(revision 0)
@@ -0,0 +1,56 @@
+import unittest
+from django.forms import ValidationError
+from django.contrib.localflavor.lv.forms import LVPhoneField
+from django.contrib.localflavor.lv.forms import LVPostalCodeField
+from django.contrib.localflavor.lv.forms import LVIdentityNumberField 
+
+class LVPhoneFieldTestCase(unittest.TestCase):
+    """ test LVPhone field """
+    def test_valid(self):
+        """ test valid phone number """
+        field = LVPhoneField()
+        self.assertEquals(field.clean("27175629"), "27175629")
+    def test_invalid(self):
+        """ test invalid phone number """
+        field = LVPhoneField()
+        self.assertRaises(ValidationError, field.clean, "7175629")
+
+
+class LVIdentityNumberFieldTestCase(unittest.TestCase):
+    def setUp(self):
+        self.field = LVIdentityNumberField()
+    def test_valid(self):
+        """ 
+        test valid identity number field un publicly known identity number of 
+        Aivars Lembergs
+        """
+        self.assertEquals(self.field.clean("260953-11667"), "26095311667")
+    def test_with_invalid_date_and_valid_checksum(self):
+        """ test with invalid date and valid checksum """
+        self.assertRaises(ValidationError, self.field.clean, "300290-11545")
+    def test_with_valid_date_and_invalid_checksum(self):
+        """ ValidationError on valid date and invalid checksum """
+        self.assertRaises(ValidationError, self.field.clean, "251278-11634")
+    def test_with_characters_inside(self):
+        """ test that identity should fail if it contains characters """
+        self.assertRaises(ValidationError, self.field.clean, "abcdef-12145")
+    def test_length_validation(self):
+        self.assertRaises(ValidationError, self.field.clean, "080690-111711")
+        self.assertRaises(ValidationError, self.field.clean, "080690-1177")
+        
+class LVPostalCodeFieldTestCase(unittest.TestCase):
+    def setUp(self):
+        self.field = LVPostalCodeField()
+    def test_with_invalid_prefix(self):
+        """ all postal code`s have prefix LV """
+        self.assertRaises(ValidationError, self.field.clean, "LR-1024")
+    def test_with_invalid_code(self):
+        """ all postal codes contain prefix, dash and numbers """
+        self.assertRaises(ValidationError, self.field.clean, "LV-10S3")
+    def test_with_invalid_digits(self):
+        """ there is just 4 digits """
+        self.assertRaises(ValidationError, self.field.clean, "LV-10244")
+        self.assertRaises(ValidationError, self.field.clean, "LV-102")
+    def test_valid(self):
+        self.assertEqual(self.field.clean("LV-1024"), "LV-1024")
+        
Index: AUTHORS
===================================================================
--- AUTHORS	(revision 13984)
+++ AUTHORS	(working copy)
@@ -517,6 +517,7 @@
     Gasper Zejn <zejn@kiberpipa.org>
     Jarek Zgoda <jarek.zgoda@gmail.com>
     Cheng Zhang
+    Kristaps Kulis <Kristaps.Kulis@Gmail.com>
 
 A big THANK YOU goes to:
 
Index: docs/ref/contrib/localflavor.txt
===================================================================
--- docs/ref/contrib/localflavor.txt	(revision 13984)
+++ docs/ref/contrib/localflavor.txt	(working copy)
@@ -53,6 +53,7 @@
     * Italy_
     * Japan_
     * Kuwait_
+    * Latvia_
     * Mexico_
     * `The Netherlands`_
     * Norway_
@@ -100,6 +101,7 @@
 .. _Italy: `Italy (it)`_
 .. _Japan: `Japan (jp)`_
 .. _Kuwait: `Kuwait (kw)`_
+.. _Latvia: `Latvia (lv)`_
 .. _Mexico: `Mexico (mx)`_
 .. _Norway: `Norway (no)`_
 .. _Peru: `Peru (pe)`_
@@ -468,6 +470,27 @@
     * The birthdate of the person is a valid date.
     * The calculated checksum equals to the last digit of the Civil ID.
 
+Latvia (``lv``)
+===============
+.. class:: lv.forms.LVPhoneField
+
+    A form field that validates input as Latvian phone number. A valid phone
+    number must consist of 8 digits
+
+.. class:: lv.forms.LVPostalCodeField
+
+    A form field that validates input as Latvian postal code number. A valid 
+    postal code number must start with LV- and contain 4 digits
+
+.. class:: lv.forms.LVIdentityNumberField
+
+    A form field that validates input as Latvian identity number. A valid identity
+    number must obey the following rules:
+
+    * The number starts with 6 digits, followed by dash and then 5 digits
+    * The first 6 digits form valid birthdate of person
+    * The last digit equals to calculated checksum
+
 Mexico (``mx``)
 ===============
 
