modules/i18n.py
def subscribe_keywords(language):
    if language == "English":
        return ["remind", "join", "born"]
    elif language == "Hindi":
        return [hindi_remind(), hindi_information(), hindi_born()]
    else:
        return []
modules/utils.py
def remove_nondigit_characters(phone_number):
	return re.sub("[^0-9]", "", phone_number)
modules/i18n.py
def hindi_remind():
    return u'\u0938\u094d\u092e\u0930\u0923'
modules/date_helper.py
def date_to_date_string(date):
    return '{d}/{m}/{y}'.format(d = date.day,
                                m = date.month,
                                y = date.year)
modules/date_helper.py
def datetime_string_mdy_to_datetime(date_string):
	return  datetime_from_date_string(date_string, "%m/%d/%Y %I:%M:%S %p").replace(tzinfo=timezone.get_default_timezone())
modules/date_helper.py
def date_string_dmy_to_date(date_string):
	for fmt in ["%d-%m-%Y", "%d/%m/%Y"]:
		try:
			return  datetime_from_date_string(date_string, fmt).date()
		except ValueError:
			pass
	raise ValueError("No valid day-month-year date format")
modules/date_helper.py
def date_string_to_date(date_string):
    sep = "-" if "-" in date_string else "/"
    if len(date_string.split(sep)) < 3:
        raise ValueError()
    year = "%Y" if len(date_string.split(sep)[2]) == 4 else "%y"
    pattern = "%d" + sep + "%m" + sep + year
    return datetime.strptime(date_string, pattern).date()
modules/utils.py
def phone_number_is_valid(phone_number):
    """Match any number starting with 91 or +91 that has another
        9 to 15 digits"""
    pattern = '^\+?91?\d{9,15}$'
    prepared_phone_number = prepare_phone_number(phone_number)
    return re.match(pattern, prepared_phone_number)
modules/date_helper.py
def date_string_ymd_to_date(date_string):
	for fmt in ["%Y-%m-%d", "%Y/%m/%d"]:
		try:
			return datetime_from_date_string(date_string, fmt).date()
		except ValueError:
			pass
	raise ValueError("No valid year-month-day date format")
modules/utils.py
def keywords_without_word(language, word):
	new_keys = subscribe_keywords(language)
	if word in new_keys:
		new_keys.remove(word)
	return new_keys
modules/date_helper.py
def try_parsing_gen_date(date_string):
	try:
	    return date_string_ymd_to_date(date_string)
	except ValueError:
		return date_string_mdy_to_date(date_string)
modules/i18n.py
def fourteen_week_reminder_one_day(language):
    if language == "English":
        return "Your child is eligible to receive a free course of vaccines. {name} has their scheduled vaccination tomorrow."
    elif language == "Hindi":
        return u'1 \u0926\u093f\u0928 \u092e\u0947\u0902 {name} \u0915\u0940 \u091f\u0940\u0915\u093e\u0915\u0930\u0923 \u0915\u0930\u0935\u093e\u090f\u0901 \u090f\u0935\u0902 \u0916\u093c\u0924\u0930\u0928\u093e\u0915 \u092c\u0940\u092e\u093e\u0930\u093f\u0913\u0902 \u0938\u0947 \u092c\u091a\u093e\u090f\u0901.'
    elif language == "Gujarati":
        return u'\u0aa1\u0ac9\u0a95\u0acd\u0a9f\u0ab0\u0ac9 \u0a8f \u0ae7 \u0aa6\u0abf\u0ab5\u0ab8\u0aae\u0abe\u0a82  {name} \u0aa8\u0ac7 \u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0aae\u0abe\u0a9f\u0ac7 \u0ab8\u0ac2\u0a9a\u0ab5\u0acd\u0aaf\u0ac1 \u0a9b\u0ac7.'
modules/i18n.py
def msg_unsubscribe(language):
    if language == "English":
        return "You have been unsubscribed from CSH health reminders."
    elif language == "Hindi":
        return u'\u0906\u092a\u0915\u0940 \u0938\u0926\u0938\u094d\u092f\u0924\u093e \u0938\u092e\u093e\u092a\u094d\u0924 \u0915\u0930 \u0926\u0940 \u0917\u092f\u0940 \u0939\u0948.'
modules/i18n.py
def nine_month_reminder_one_day(language):
    return six_week_reminder_one_day(language)
modules/i18n.py
def sixteen_month_reminder_one_day(language):
    return ten_week_reminder_one_day(language)
modules/i18n.py
def ten_week_reminder_one_day(language):
    if language == "English":
        return "{name} is due for their important vaccinations tomorrow. Please do so then."
    elif language == "Hindi":
        return u'\u091c\u093c\u093f\u092e\u094d\u092e\u0947\u0926\u093e\u0930 \u092e\u093e\u0924\u093e \u0939\u094b\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u0906\u092a\u0915\u094b \u092c\u0927\u093e\u0908. 1 \u0926\u093f\u0928 \u092e\u0947\u0902 {name} \u0915\u0947 \u091c\u093c\u0930\u0942\u0930\u0940 \u091f\u0940\u0915\u093e\u0915\u0930\u0923 \u0915\u0947 \u0932\u093f\u090f \u0906\u092a \u0938\u0947 \u092e\u0941\u0932\u093e\u0915\u093c\u093e\u0924 \u0939\u094b\u0917\u0940.'
    elif language == "Gujarati":
        return u'{name} \u0aa8 \u0ac1\u0a82\u0ae7 \u0aa6\u0abf\u0ab5\u0ab8\u0aae \u0ac1\u0a82\u0aae\u0ab9\u0aa4\u0acd\u0ab5\u0aaa\u0ac2\u0aa3\u0aa3\u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0aa6\u0aa8\u0aaf\u0aa4 \u0a9b\u0ac7. \u0aa4\u0acb \u0a95\u0ac3\u0aaa \u0a95\u0ab0\u0ac0\u0ac1\u0a82\u0aa8\u0ac7\u0aaa\u0a9b\u0ac0 \u0a8f \u0a95\u0ab0\u0a9c\u0acb.'
modules/date_helper.py
def date_string_mdy_to_date(date_string):
	for fmt in ["%m-%d-%Y", "%m/%d/%Y"]:
		try:
			return  datetime_from_date_string(date_string, fmt).date()
		except ValueError:
			pass
	raise ValueError("No valid month-day-year date format")
modules/i18n.py
def msg_already_sub(language):
    if language == "English":
        return "You are already registered to receive CSH health reminders."
    elif language == "Hindi":
        return u'\u0906\u092a \u092a\u0939\u0932\u0947 \u0938\u0947 \u0939\u0940 \u0938\u0940.\u090f\u0938.\u091a \u0938\u094d\u0935\u093e\u0938\u094d\u0925\u094d\u092f \u0938\u094d\u092e\u0930\u0923 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u092a\u0902\u091c\u0940\u0915\u0943\u0924 \u0939\u0948\u0902.'
modules/utils.py
def prepare_phone_number(phone_number):
	if phone_number == None:
		return ""
	stripped_phone_number = remove_nondigit_characters(phone_number)
	if stripped_phone_number == "0" * len(stripped_phone_number):
		return ""
	elif len(stripped_phone_number) < 10:
		return phone_number
	return add_country_code_to_phone_number(stripped_phone_number)
modules/i18n.py
def six_week_reminder_one_day(language):
    if language == "English":
        return "{name} is due for their important vaccinations tomorrow. Please do so then."
    elif language == "Hindi":
        return u'\u0905\u0917\u0932\u0947 1 \u0926\u093f\u0928 \u092e\u0947\u0902 {name} \u0915\u0940 \u091c\u093c\u0930\u0942\u0930\u0940 \u091f\u0940\u0915\u093e\u0915\u0930\u0923 \u0905\u0935\u0936\u094d\u092f \u0915\u0930\u0935\u093e\u090f\u0901.'
    elif language == "Gujarati":
        return u'{name} \u0aa8 \u0ac1\u0a82\u0ae7 \u0aa6\u0abf\u0ab5\u0ab8\u0aae \u0ac1\u0a82\u0aae\u0ab9\u0aa4\u0acd\u0ab5\u0aaa\u0ac2\u0aa3\u0aa3\u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0aa6\u0aa8\u0aaf\u0aa4 \u0a9b\u0ac7. \u0aa4\u0acb \u0a95\u0ac3\u0aaa \u0a95\u0ab0\u0ac0\u0ac1\u0a82\u0aa8\u0ac7\u0aaa\u0a9b\u0ac0 \u0a8f \u0a95\u0ab0\u0a9c\u0acb.'
modules/i18n.py
def six_week_reminder_seven_days(language):
    if language == "English":
        return "{name} has their scheduled vaccination in 7 days. Without this vaccination your child will be vulnerable to deadly diseases."
    elif language == "Hindi":
        return u'7 \u0926\u093f\u0928\u094b\u0902 \u092e\u0947\u0902 {name} \u0915\u093e \u091f\u0940\u0915\u093e\u0915\u0930\u0923 \u0915\u0930\u0935\u093e\u090f\u0901 \u090f\u0935\u0902 \u0916\u093c\u0924\u0930\u0928\u093e\u0915 \u092c\u0940\u092e\u093e\u0930\u093f\u0913\u0902 \u0938\u0947 \u092c\u091a\u093e\u090f\u0901.'
    elif language == "Gujarati":
        return u'{name} \u0aa8 \u0ac1\u0a82\u0aed \u0aa6\u0abf\u0ab5\u0ab8 \u0aae \u0ac1\u0aa8 \u0ac1\u0a82\u0aed \u0aa6\u0abf\u0ab5\u0ab8 \u0aae \u0ac1\u0a82\u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0ab8 \u0aa6\u0aa8\u0aa6\u0abf\u0aa4 \u0a9b\u0ac7. \u0a86 \u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0ab5\u0a97\u0ab0 \u0aa4\u0aae \u0ab0\u0ac1\u0a82 \u0aac \u0ab3\u0a95 \u0a9c\u0ac0\u0ab5\u0ab2\u0ac7\u0aa3 \u0ab0\u0acb\u0a97\u0acb \u0aae \u0a9f\u0ac7\u0ab8\u0ac1\u0a82\u0ab5\u0ac7\u0abf\u0aa8\u0ab6\u0ac0\u0ab2 \u0ab0\u0ab9\u0ac7\u0ab6\u0ac7.'
modules/i18n.py
def msg_subscribe(language):
    if language == "English":
        return "{name} has been subscribed to CSH health reminders. Text END to " + TEXTLOCAL_PHONENUMBER + " to unsubscribe."
    elif language == "Hindi":
        return u'{name} \u0938\u0940 \u090f\u0938 \u090f\u091a \u0939\u0947\u0932\u094d\u0925 \u0905\u0928\u0941\u0938\u094d\u092e\u0930\u0928 \u0915\u0947 \u0938\u0926\u0938\u094d\u092f \u0939\u0948\u0902. \u0938\u0926\u0938\u094d\u092f\u0924\u093e \u0930\u0926\u094d\u0926 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u0932\u093f\u0916\u0947\u0902 "END" \u0914\u0930 \u092d\u0947\u0902\u091c \u0926\u0947 ' + TEXTLOCAL_PHONENUMBER + u' \u092a\u0930.'
modules/i18n.py
def sixteen_month_reminder_seven_days(language):
    return ten_week_reminder_seven_days(language)
modules/i18n.py
def ten_week_reminder_seven_days(language):
    if language == "English":
        return "{name} is eligible for a free vaccination in 7 days. Without this vaccination your child will be vulnerable to deadly diseases."
    elif language == "Hindi":
        return u'7 \u0926\u093f\u0928\u094b\u0902 \u092e\u0947\u0902 {name} \u0915\u0940 \u0928\u093f\u0903\u0936\u0941\u0932\u094d\u0915 \u091f\u0940\u0915\u093e\u0915\u0930\u0923 \u0915\u0930\u0935\u093e\u090f\u0901 \u090f\u0935\u0902 \u0916\u093c\u0924\u0930\u0928\u093e\u0915 \u092c\u0940\u092e\u093e\u0930\u093f\u0913\u0902 \u0938\u0947 \u092c\u091a\u093e\u090f\u0901.'
    elif language == "Gujarati":
        return u'{name} \u0aed \u0aa6\u0abf\u0ab5\u0ab8\u0aae \u0ac1\u0a82\u0aae\u0aab\u0aa4 \u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0aae \u0a9f\u0ac7\u0aaa \u0aa4\u0acd\u0ab0 \u0a9b\u0ac7. \u0a86 \u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0ab5\u0a97\u0ab0 \u0aa4\u0aae \u0ab0\u0ac2 \u0aac \u0ab3\u0a95 \u0a9c\u0ac0\u0ab5\u0ab2\u0ac7\u0aa3 \u0ab0\u0acb\u0a97\u0acb \u0aae \u0a9f\u0ac7\u0ab8\u0ac1\u0a82\u0ab5\u0ac7\u0abf\u0aa8\u0ab6\u0ac0\u0ab2 \u0ab0\u0ab9\u0ac7\u0ab6\u0ac7.'
modules/utils.py
def quote(word):
    return u"`{}`".format(word)
modules/i18n.py
def five_year_reminder_one_day(language):
    return fourteen_week_reminder_one_day(language)
modules/i18n.py
def fourteen_week_reminder_seven_days(language):
    if language == "English":
        return "Thank you for being a responsible mother. {name} is due for their important vaccinations in 7 days. Please do so then."
    elif language == "Hindi":
        return u'{name} \u0915\u0947 \u091f\u0940\u0915\u093e\u0915\u0930\u0923 7 \u0926\u093f\u0928\u094b\u0902 \u092e\u0947\u0902 \u0905\u0935\u0936\u094d\u092f \u0915\u0930\u0935\u093e\u090f\u0901.'
    elif language == "Gujarati":
        return u'\u0a8f\u0a95 \u0a9c\u0ab5 \u0aac\u0abf \u0ab0 \u0aae \u0aa4 \u0ab9\u0acb\u0ab5 \u0aac\u0abf\u0ab2 \u0aa7\u0aa8\u0acd\u0aaf\u0ab5 \u0abf. {name} \u0aa8 \u0ac1\u0a82\u0aed \u0aa6\u0abf\u0ab5\u0ab8\u0aae \u0ac1\u0a82\u0aae\u0ab9\u0aa4\u0acd\u0ab5\u0aaa\u0ac2\u0aa3\u0aa3\u0ab0\u0ab8\u0ac0\u0a95\u0ab0\u0aa3 \u0aa6\u0aa8\u0aaf\u0aa4 \u0a9b\u0ac7. \u0aa4\u0acb \u0a95\u0ac3\u0aaa \u0a95\u0ab0\u0ac0\u0ac1\u0a82\u0aa8\u0ac7\u0aaa\u0a9b\u0ac0 \u0a8f \u0a95\u0ab0\u0a9c\u0acb.'
modules/i18n.py
def hindi_born():
    return u'\u091c\u0928\u094d\u092e'
modules/i18n.py
def verify_pregnant_signup_birthdate(language):
    if language == "English":
        return "You signed up for health reminders while pregnant. If your child has been born, text 'BORN Name DD-MM-YY' to "+ TEXTLOCAL_PHONENUMBER + " to register for  English. An example message is 'BORN Aarav 14-01-17' where 'Aarav' is your child's first name and '14-01-17' is your child's birthday."
    elif language == "Hindi":
        return u'\u0905\u092a\u0928\u0940 \u0917\u0930\u094d\u092d\u093e\u0935\u0938\u094d\u0920\u093e \u0915\u0947 \u0926\u094c\u0930\u093e\u0928 \u0906\u092a\u0928\u0947 \u0938\u094d\u0935\u093e\u0938\u094d\u0925\u094d\u092f \u0938\u094d\u092e\u0930\u0923 \u0915\u0940 \u0938\u0926\u0938\u094d\u092f\u0924\u093e \u0932\u0940 \u0925\u0940. \u092f\u0926\u093f \u0906\u092a\u0915\u093e \u092c\u091a\u094d\u091a\u093e \u091c\u0928\u094d\u092e \u0932\u0947 \u091a\u0942\u0915\u093e \u0939\u0948 \u0924\u094b \u0932\u093f\u0916\u0947 \u201c \u091c\u0928\u094d\u092e \u0928\u093e\u092e DD-MM-YY \u201d \u0914\u0930 \u092d\u0947\u0902\u091c \u0926\u0947 \u201c ' + TEXTLOCAL_PHONENUMBER + u' \u201d \u092a\u0930 \u0939\u093f\u0902\u0926\u0940 \u092e\u0947\u0902 \u092a\u0902\u091c\u0940\u0915\u0930\u0923 \u0915\u0947 \u0932\u093f\u090f.'
modules/utils.py
def is_not_ascii(message):
	return any(ord(char) >= 128 for char in message)
modules/i18n.py
def msg_failed_date(language):
    if language == "English":
        return "Sorry, the date format was incorrect. An example message is 'Remind Sai 14-01-17' where 'Sai' is your child's first name and '14-01-17'' is their birthday."
    elif language == "Hindi":
        return u'\u0915\u094d\u0937\u092e\u093e \u0915\u0940\u091c\u093f\u092f\u0947, \u0924\u093e\u0930\u0940\u0916 \u0915\u093e \u092a\u094d\u0930\u093e\u0930\u0942\u092a \u0917\u0932\u0924 \u0939\u0948.'
modules/date_helper.py
def try_parsing_partner_date(date_string):
	try:
		return date_string_dmy_to_date(date_string)
	except ValueError:
		return date_string_ymd_to_date(date_string)
modules/i18n.py
def hindi_information():
    return u'\u0907\u0924\u094d\u0924\u093f\u0932\u093e'
modules/date_helper.py
def date_is_valid(date_string):
    try:
        date = date_string_to_date(date_string)
        too_old = date.year < datetime.now().year - 18
        too_young = date.year > datetime.now().year + 2
        return (not too_old and not too_young)
    except ValueError:
        return False
modules/i18n.py
def five_year_reminder_seven_days(language):
    return fourteen_week_reminder_seven_days(language)
modules/i18n.py
def msg_failure(language):
    if language == "English":
        return "Sorry, we didn't understand that message. Text END to " + TEXTLOCAL_PHONENUMBER + " to unsubscribe."
    elif language == "Hindi":
        return u'\u0915\u094d\u0937\u092e\u093e \u0915\u0930\u0947\u0902, \u0939\u092e\u0928\u0947 \u0909\u0938 \u0938\u0902\u0926\u0947\u0936 \u0915\u094b \u0928\u0939\u0940\u0902 \u0938\u092e\u091d\u093e. \u0938\u0926\u0938\u094d\u092f\u0924\u093e \u0930\u0926\u094d\u0926 \u0915\u0930\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u0932\u093f\u0916\u0947\u0902 "END" \u0914\u0930 \u092d\u0947\u0902\u091c \u0926\u0947 ' + TEXTLOCAL_PHONENUMBER + ' \u092a\u0930.'
modules/i18n.py
def nine_month_reminder_seven_days(language):
    return six_week_reminder_seven_days(language)
modules/utils.py
def add_country_code_to_phone_number(phone_number):
	if not phone_number:
		return phone_number

	begins_with_nine_one = re.match("^91", phone_number)
		
	if not begins_with_nine_one:
		phone_number = "91" + phone_number

	return phone_number
modules/date_helper.py
def datetime_string_ymd_to_datetime(date_string):
		try:
			return datetime_from_date_string(date_string, "%Y-%m-%d %H:%M:%S").replace(tzinfo=timezone.get_default_timezone())
		except ValueError:
			logging.error("Invalid datetime entry for message: " + quote(date_string))
			return datetime.now().replace(tzinfo=timezone.get_default_timezone())


Question: from datetime import datetime
from django.test import TestCase
from django.utils import timezone
from freezegun import freeze_time
from mock import patch
from modules.utils import quote, phone_number_is_valid, remove_nondigit_characters, \
                                add_country_code_to_phone_number, prepare_phone_number, \
                                keywords_without_word, is_not_ascii
from modules.date_helper import date_string_to_date, date_is_valid, \
                                date_to_date_string, date_string_dmy_to_date, \
                                date_string_mdy_to_date, date_string_ymd_to_date, \
                                try_parsing_partner_date, try_parsing_gen_date, \
                                datetime_string_mdy_to_datetime, datetime_string_ymd_to_datetime
from modules.i18n import hindi_information, hindi_remind, hindi_born, \
                            subscribe_keywords, six_week_reminder_seven_days, \
                            six_week_reminder_one_day, ten_week_reminder_seven_days, \
                            ten_week_reminder_one_day, fourteen_week_reminder_seven_days, \
                            fourteen_week_reminder_one_day, nine_month_reminder_seven_days, \
                            nine_month_reminder_one_day, sixteen_month_reminder_seven_days, \
                            sixteen_month_reminder_one_day, five_year_reminder_seven_days, \
                            five_year_reminder_one_day, verify_pregnant_signup_birthdate, \
                            msg_subscribe, msg_unsubscribe, msg_already_sub, msg_failure, \
                            msg_failed_date
from six import u


FAKE_NOW = datetime(2017, 12, 1, 15, 10, 3)

class QuoteTests(TestCase):
    def test_quote(self):
        self.assertEqual(quote("text"), "`text`")

    def test_quote_with_a_float(self):
        self.assertEqual(quote(2.0), "`2.0`")


class DateIsValidTests(TestCase):
    def test_normal_date(self):
        self.assertTrue(date_is_valid("25/11/2015"))
        self.assertTrue(date_is_valid("11/12/2012"))
        self.assertTrue(date_is_valid("09/02/2001"))

    def test_short_year_date(self):
        self.assertTrue(date_is_valid("25/11/15"))
        self.assertTrue(date_is_valid("11/12/12"))
        self.assertTrue(date_is_valid("09/02/01"))

    def test_hypen_separated_date(self):
        self.assertTrue(date_is_valid("25-11-2015"))
        self.assertTrue(date_is_valid("11-12-2012"))
        self.assertTrue(date_is_valid("09-02-2001"))

    def test_one_digit_date(self):
        self.assertTrue(date_is_valid("05-05-2015"))
        self.assertTrue(date_is_valid("09-02-2001"))
        self.assertTrue(date_is_valid("05-5-2015"))
        self.assertTrue(date_is_valid("09-2-2001"))
        self.assertTrue(date_is_valid("5-05-2015"))
        self.assertTrue(date_is_valid("5-05-2015"))
        self.assertTrue(date_is_valid("9-2-2001"))
        self.assertTrue(date_is_valid("9-2-2001"))
        
    def test_leap_year_dates(self):
        self.assertTrue(date_is_valid("29/02/2012"))
        self.assertFalse(date_is_valid("29/02/2013"))
        self.assertTrue(date_is_valid("29/02/2016"))
        self.assertFalse(date_is_valid("29/02/2017"))

    def test_reject_bogus_dates(self):
        self.assertFalse(date_is_valid("Bogus"))
        self.assertFalse(date_is_valid("00/00/00"))
        self.assertFalse(date_is_valid("31/02/2015"))
        self.assertFalse(date_is_valid("43/11/2015"))

    def test_reject_mm_dd_dates(self):
        self.assertFalse(date_is_valid("11-25-2015"))
        self.assertFalse(date_is_valid("31/06/2017"))
        self.assertFalse(date_is_valid("29/02/2017"))
        self.assertFalse(date_is_valid("15/15/2015"))
    
    def test_reject_too_far_in_future(self):
        self.assertFalse(date_is_valid("25/11/2133"))
    
    def test_reject_too_far_in_past(self):
        self.assertFalse(date_is_valid("11/12/1991"))


class DateStringToDateTests(TestCase):
    def test_date_strings_get_converted_to_dates(self):

Answer:         self.assertEqual(date_string_to_date("25/11/2015"), datetime(2015, 11, 25, 0, 0).date())