Repository: joke2k/faker

Issue:
Norwegian ssn returns the wrong format for the date part 
SSN for no_NO returns the wrong format of the date part.

### Steps to reproduce

As @cloveras pointed out:
Using December 31 1999 as the date of birth (YYYYMMDD):
ssn('19991231','M')

This results in SSNs like these:
99123145123
99123108724
99123127532

### Expected behavior

The correct format is DDMMYY.

### Actual behavior

These start with the date of birth in YYMMDD format.


Comments:

Patch:
diff --git a/faker/providers/ssn/en_CA/__init__.py b/faker/providers/ssn/en_CA/__init__.py
index 0349b889..11f4acc6 100644
--- a/faker/providers/ssn/en_CA/__init__.py
+++ b/faker/providers/ssn/en_CA/__init__.py
@@ -2,36 +2,81 @@
 from __future__ import unicode_literals
 from .. import Provider as SsnProvider
 
+def checksum(sin):
+    """
+    Determine validity of a Canadian Social Insurance Number.
+    Validation is performed using a modified Luhn Algorithm.  To check
+    the Every second digit of the SIN is doubled and the result is
+    summed.  If the result is a multiple of ten, the Social Insurance
+    Number is considered valid.
+
+    https://en.wikipedia.org/wiki/Social_Insurance_Number
+    """
+
+    # Remove spaces and create a list of digits.
+    checksumCollection = list(sin.replace(' ', ''))
+    checksumCollection = [int(i) for i in checksumCollection]
+
+    # Discard the last digit, we will be calculating it later.
+    checksumCollection[-1] = 0
+
+    # Iterate over the provided SIN and double every second digit.
+    # In the case that doubling that digit results in a two-digit
+    # number, then add the two digits together and keep that sum.
+
+    for i in range(1, len(checksumCollection), 2):
+        result = checksumCollection[i] * 2
+        if result < 10:
+            checksumCollection[i] = result
+        else:
+            checksumCollection[i] = result - 10 + 1
+
+    # The appropriate checksum digit is the value that, when summed
+    # with the first eight values, results in a value divisible by 10
+
+    check_digit = 10 - (sum(checksumCollection) % 10)
+    check_digit = (0 if check_digit == 10 else check_digit)
+
+    return check_digit
 
 class Provider(SsnProvider):
 
-    # in order to create a valid SIN we need to provide a number that passes a simple modified Luhn Algorithmn checksum
-    # this function essentially reverses the checksum steps to create a random
-    # valid SIN (Social Insurance Number)
+    # In order to create a valid SIN we need to provide a number that 
+    # passes a simple modified Luhn Algorithm checksum. 
+    # 
+    # This function reverses the checksum steps to create a random
+    # valid nine-digit Canadian SIN (Social Insurance Number) in the
+    # format '### ### ###'.
     def ssn(self):
 
-        # create an array of 8 elements initialized randomly
-        digits = self.generator.random.sample(range(10), 8)
+        # Create an array of 8 elements initialized randomly.
+        digits = self.generator.random.sample(range(9), 8)
+
+        # The final step of the validation requires that all of the 
+        # digits sum to a multiple of 10. First, sum the first 8 and
+        # set the 9th to the value that results in a multiple of 10.
+        check_digit = 10 - (sum(digits) % 10)
+        check_digit = (0 if check_digit == 10 else check_digit)
 
-        # All of the digits must sum to a multiple of 10.
-        # sum the first 8 and set 9th to the value to get to a multiple of 10
-        digits.append(10 - (sum(digits) % 10))
+        digits.append(check_digit)
 
-        # digits is now the digital root of the number we want multiplied by the magic number 121 212 121
-        # reverse the multiplication which occurred on every other element
+        # digits is now the digital root of the number we want 
+        # multiplied by the magic number 121 212 121. The next step is
+        # to reverse the multiplication which occurred on every other
+        # element.
         for i in range(1, len(digits), 2):
             if digits[i] % 2 == 0:
-                digits[i] = (digits[i] / 2)
+                digits[i] = (digits[i] // 2)
             else:
-                digits[i] = (digits[i] + 9) / 2
+                digits[i] = (digits[i] + 9) // 2
 
-        # build the resulting SIN string
+        # Build the resulting SIN string.
         sin = ""
-        for i in range(0, len(digits), 1):
+        for i in range(0, len(digits)):
             sin += str(digits[i])
-            # add a space to make it conform to normal standards in Canada
-            if i % 3 == 2:
+            # Add a space to make it conform to Canadian formatting.
+            if i in (2,5):
                 sin += " "
 
-        # finally return our random but valid SIN
+        # Finally return our random but valid SIN.
         return sin
diff --git a/faker/providers/ssn/no_NO/__init__.py b/faker/providers/ssn/no_NO/__init__.py
index 207831b8..2f171d42 100644
--- a/faker/providers/ssn/no_NO/__init__.py
+++ b/faker/providers/ssn/no_NO/__init__.py
@@ -71,7 +71,7 @@ class Provider(SsnProvider):
                 gender_num = self.generator.random.choice((0, 2, 4, 6, 8))
             elif gender == 'M':
                 gender_num = self.generator.random.choice((1, 3, 5, 7, 9))
-            pnr = birthday.strftime('%y%m%d') + suffix.zfill(2) + str(gender_num)
+            pnr = birthday.strftime('%d%m%y') + suffix.zfill(2) + str(gender_num)
             pnr_nums = [int(ch) for ch in pnr]
             k1 = checksum(Provider.scale1, pnr_nums)
             k2 = checksum(Provider.scale2, pnr_nums + [k1])


Test patch:
diff --git a/tests/providers/test_ssn.py b/tests/providers/test_ssn.py
index abf33e63..ea58fcf8 100644
--- a/tests/providers/test_ssn.py
+++ b/tests/providers/test_ssn.py
@@ -7,13 +7,29 @@ import re
 from datetime import datetime
 
 from faker import Faker
+from faker.providers.ssn.en_CA import checksum as ca_checksum
 from faker.providers.ssn.et_EE import checksum as et_checksum
 from faker.providers.ssn.fi_FI import Provider as fi_Provider
 from faker.providers.ssn.hr_HR import checksum as hr_checksum
 from faker.providers.ssn.pt_BR import checksum as pt_checksum
 from faker.providers.ssn.pl_PL import checksum as pl_checksum, calculate_month as pl_calculate_mouth
-from faker.providers.ssn.no_NO import checksum as no_checksum, Provider
+from faker.providers.ssn.no_NO import checksum as no_checksum, Provider as no_Provider
 
+class TestEnCA(unittest.TestCase):
+    def setUp(self):
+        self.factory = Faker('en_CA')
+        self.factory.seed(0)
+
+    def test_ssn(self):
+        for _ in range(100):
+            sin = self.factory.ssn()
+
+            # Ensure that generated SINs are 11 characters long
+            # including spaces, consist of spaces and digits only, and
+            # satisfy the validation algorithm. 
+            assert len(sin) == 11
+            assert sin.replace(' ','').isdigit()
+            assert ca_checksum(sin) == int(sin[-1])
 
 class TestEtEE(unittest.TestCase):
     """ Tests SSN in the et_EE locale """
@@ -170,8 +186,8 @@ class TestNoNO(unittest.TestCase):
         self.factory = Faker('no_NO')
 
     def test_no_NO_ssn_checksum(self):
-        self.assertEqual(no_checksum([0, 1, 0, 2, 0, 3, 9, 8, 7], Provider.scale1), 6)
-        self.assertEqual(no_checksum([0, 1, 0, 2, 0, 3, 9, 8, 7, 6], Provider.scale2), 7)
+        self.assertEqual(no_checksum([0, 1, 0, 2, 0, 3, 9, 8, 7], no_Provider.scale1), 6)
+        self.assertEqual(no_checksum([0, 1, 0, 2, 0, 3, 9, 8, 7, 6], no_Provider.scale2), 7)
 
     def test_no_NO_ssn(self):
         for _ in range(100):
@@ -180,9 +196,11 @@ class TestNoNO(unittest.TestCase):
             self.assertEqual(len(ssn), 11)
 
     def test_no_NO_ssn_dob_passed(self):
-        date_of_birth = '20010203'
-        ssn = self.factory.ssn(dob=date_of_birth)
-        self.assertEqual(ssn[:6], date_of_birth[2:])
+        test_data = [('20010203', '030201'),
+                     ('19991231', '311299')]
+        for date_of_birth, expected_dob_part in test_data:
+            ssn = self.factory.ssn(dob=date_of_birth)
+            self.assertEqual(ssn[:6], expected_dob_part)
 
     def test_no_NO_ssn_invalid_dob_passed(self):
         with self.assertRaises(ValueError):