From 77668afa111cab05e4295bf881112b21ef30cf7c Mon Sep 17 00:00:00 2001
From: Bill DeRusha <bill@edx.org>
Date: Tue, 12 Jan 2016 16:34:50 -0500
Subject: [PATCH] Update age calculation to be more conservative.

---
 common/djangoapps/student/models.py             | 17 ++++++++++++++---
 .../student/tests/test_create_account.py        |  5 +++--
 .../tests/test_user_profile_properties.py       |  8 ++++++--
 3 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py
index 64d21af18b4..878cdd2d42c 100644
--- a/common/djangoapps/student/models.py
+++ b/common/djangoapps/student/models.py
@@ -292,7 +292,7 @@ class UserProfile(models.Model):
         year_of_birth = self.year_of_birth
         year = datetime.now(UTC).year
         if year_of_birth is not None:
-            return year - year_of_birth
+            return self._calculate_age(year, year_of_birth)
 
     @property
     def level_of_education_display(self):
@@ -364,14 +364,25 @@ class UserProfile(models.Model):
         if date is None:
             age = self.age
         else:
-            age = date.year - year_of_birth
+            age = self._calculate_age(date.year, year_of_birth)
 
-        return age <= age_limit
+        return age < age_limit
 
     def __enumerable_to_display(self, enumerables, enum_value):
         """ Get the human readable value from an enumerable list of key-value pairs. """
         return dict(enumerables)[enum_value]
 
+    def _calculate_age(self, year, year_of_birth):
+        """Calculate the youngest age for a user with a given year of birth.
+
+        :param year: year
+        :param year_of_birth: year of birth
+        :return: youngest age a user could be for the given year
+        """
+        # There are legal implications regarding how we can contact users and what information we can make public
+        # based on their age, so we must take the most conservative estimate.
+        return year - year_of_birth - 1
+
     @classmethod
     def country_cache_key_name(cls, user_id):
         """Return cache key name to be used to cache current country.
diff --git a/common/djangoapps/student/tests/test_create_account.py b/common/djangoapps/student/tests/test_create_account.py
index 232091d19d8..55aa4d22f7b 100644
--- a/common/djangoapps/student/tests/test_create_account.py
+++ b/common/djangoapps/student/tests/test_create_account.py
@@ -118,6 +118,7 @@ class TestCreateAccount(TestCase):
     @mock.patch('student.views.analytics.identify')
     def test_segment_tracking(self, mock_segment_identify, _):
         year = datetime.now().year
+        year_of_birth = year - 14
         self.params.update({
             "level_of_education": "a",
             "gender": "o",
@@ -125,7 +126,7 @@ class TestCreateAccount(TestCase):
             "city": "Exampleton",
             "country": "US",
             "goals": "To test this feature",
-            "year_of_birth": str(year),
+            "year_of_birth": str(year_of_birth),
             "extra1": "extra_value1",
             "extra2": "extra_value2",
         })
@@ -134,7 +135,7 @@ class TestCreateAccount(TestCase):
             'email': self.params['email'],
             'username': self.params['username'],
             'name': self.params['name'],
-            'age': 0,
+            'age': 13,
             'education': 'Associate degree',
             'address': self.params['mailing_address'],
             'gender': 'Other/Prefer Not to Say',
diff --git a/common/djangoapps/student/tests/test_user_profile_properties.py b/common/djangoapps/student/tests/test_user_profile_properties.py
index 06bd37a3a43..3c7b835d54b 100644
--- a/common/djangoapps/student/tests/test_user_profile_properties.py
+++ b/common/djangoapps/student/tests/test_user_profile_properties.py
@@ -42,11 +42,15 @@ class UserProfilePropertiesTest(TestCase):
         self.profile.save()
 
     @ddt.data(0, 1, 13, 20, 100)
-    def test_age(self, age):
+    def test_age(self, years_ago):
         """Verify the age calculated correctly."""
         current_year = datetime.datetime.now().year
-        self._set_year_of_birth(current_year - age)
+        self._set_year_of_birth(current_year - years_ago)
 
+        # In the year that your turn a certain age you will also have been a
+        # year younger than that in that same year.  We calculate age based off of
+        # the youngest you could be that year.
+        age = years_ago - 1
         self.assertEqual(self.profile.age, age)
 
     def test_age_no_birth_year(self):
-- 
GitLab