Skip to content

Instantly share code, notes, and snippets.

@Oceantidote
Created January 18, 2021 18:12
Show Gist options
  • Save Oceantidote/471eeb1b10e259e3b820a2a22a9dbedc to your computer and use it in GitHub Desktop.
Save Oceantidote/471eeb1b10e259e3b820a2a22a9dbedc to your computer and use it in GitHub Desktop.
'01': Ain
'02': Aisne
'03': Allier
'04': Alpes-de-Haute-Provence
'05': Hautes-Alpes
'06': Alpes-Maritimes
'07': Ardèche
'08': Ardennes
'09': Ariège
'10': Aube
'11': Aude
'12': Aveyron
'13': Bouches-du-Rhône
'14': Calvados
'15': Cantal
'16': Charente
'17': Charente-Maritime
'18': Cher
'19': Corrèze
'2A': Corse-du-Sud
'2B': Haute-Corse
'21': Côte-d'Or
'22': Côtes-d'Armor
'23': Creuse
'24': Dordogne
'25': Doubs
'26': Drôme
'27': Eure
'28': Eure-et-Loir
'29': Finistère
'30': Gard
'31': Haute-Garonne
'32': Gers
'33': Gironde
'34': Hérault
'35': Ille-et-Vilaine
'36': Indre
'37': Indre-et-Loire
'38': Isère
'39': Jura
'40': Landes
'41': Loir-et-Cher
'42': Loire
'43': Haute-Loire
'44': Loire-Atlantique
'45': Loiret
'46': Lot
'47': Lot-et-Garonne
'48': Lozère
'49': Maine-et-Loire
'50': Manche
'51': Marne
'52': Haute-Marne
'53': Mayenne
'54': Meurthe-et-Moselle
'55': Meuse
'56': Morbihan
'57': Moselle
'58': Nièvre
'59': Nord
'60': Oise
'61': Orne
'62': Pas-de-Calais
'63': Puy-de-Dôme
'64': Pyrénées-Atlantiques
'65': Hautes-Pyrénées
'66': Pyrénées-Orientales
'67': Bas-Rhin
'68': Haut-Rhin
'69': Rhône
'70': Haute-Saône
'71': Saône-et-Loire
'72': Sarthe
'73': Savoie
'74': Haute-Savoie
'75': Paris
'76': Seine-Maritime
'77': Seine-et-Marne
'78': Yvelines
'79': Deux-Sèvres
'80': Somme
'81': Tarn
'82': Tarn-et-Garonne
'83': Var
'84': Vaucluse
'85': Vendée
'86': Vienne
'87': Haute-Vienne
'88': Vosges
'89': Yonne
'90': Territoire de Belfort
'91': Essonne
'92': Hauts-de-Seine
'93': Seine-Saint-Denis
'94': Val-de-Marne
'95': Val-d'Oise
require "date"
require "yaml"
def french_ssn_info(number)
pattern = /^(?<gender>[12])\s?(?<year>\d{2})\s?(?<month>1[0-2]|0[1-9])\s?(?<region>\d{2})\s?\d{3}\s?\d{3}\s?(?<key>\d{2})$/
result = number.match(pattern)
if result && valid?(result)
gender = gender(result)
month = month(result)
year = year(result)
region = region(result)
return "a #{gender}, born in #{month}, #{year} in #{region}."
else
return "The number is invalid"
end
end
def gender(matchdata)
if matchdata[:gender] == "1"
"man"
else
"woman"
end
end
def month(matchdata)
Date::MONTHNAMES[matchdata[:month].to_i]
end
def year(matchdata)
if matchdata[:year].to_i < 21
"20#{matchdata[:year]}"
else
"19#{matchdata[:year]}"
end
end
def region(matchdata)
regions = YAML.load_file('data/french_departments.yml')
regions[matchdata[:region]]
end
def valid?(matchdata)
number = matchdata[0].delete(' ')[0..-3].to_i
remainder = (97 - number) % 97
remainder == matchdata[:key].to_i
end
# A 2 digits key (46, equal to the remainder of the division of (97 - ssn_without_key) by 97.)
# 46 = remainder of (97 - 1041276451089) / 97
french_ssn_info("1 84 12 76 451 089 46")
require_relative "../french_ssn"
describe "#french_ssn_info" do
it "returns 'The number is invalid' when passed an empty string" do
actual = french_ssn_info("")
expected = "The number is invalid"
expect(actual).to eq(expected)
end
it "returns 'a man, born in December, 1984 in Seine-Maritime.' when passed '1 84 12 76 451 089 46'" do
actual = french_ssn_info("1 84 12 76 451 089 46")
expected = "a man, born in December, 1984 in Seine-Maritime."
expect(actual).to eq(expected)
end
it "should reject numbers that do not match key constraints" do
actual = french_ssn_info("1 84 12 76 451 086 46")
expected = "The number is invalid"
expect(actual).to eq(expected)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment