Skip to content

Instantly share code, notes, and snippets.

@swlaschin
Last active September 13, 2021 07:54
Show Gist options
  • Save swlaschin/0678d18f8a0ed1ed1184 to your computer and use it in GitHub Desktop.
Save swlaschin/0678d18f8a0ed1ed1184 to your computer and use it in GitHub Desktop.
FsCheck properties to use to check a "how many years old" function
module PropertiesForDob =
let badAge (today:System.DateTime) (dob:System.DateTime) =
let dob = dob.Date // ignore time
let today = today.Date // ignore time
let ts = today.Subtract(dob)
ts.Days / 365 // bad implementation
let goodAge (today:System.DateTime) (dob:System.DateTime) =
let dob = dob.Date // ignore time
let today = today.Date // ignore time
let age = today.Year - dob.Year
let sameDateInBirthYear = today.AddYears(-age)
if dob.Date > sameDateInBirthYear then
age - 1
else
age
// sanity check
let ``age is near year difference`` fnAge (dob:System.DateTime) =
let dob = dob.Date // ignore time
let today = System.DateTime.Today // ignore time
let todayYear = today.Year
let dobYear = dob.Year
let age = fnAge today dob
(age <= todayYear - dobYear + 1) && (age >= todayYear - dobYear - 1)
let ``you are one year older on your birthday`` fnAge (dob:System.DateTime) =
let dob = dob.Date // ignore time
let today = System.DateTime.Today // ignore time
let todaysAge = fnAge today dob
[1.0 .. 367.0]
|> List.map (today.AddDays)
|> List.tryFind (fun date -> (fnAge date dob) = todaysAge + 1 )
|> Option.map (fun cutoverDate ->
cutoverDate.Day = dob.Day && cutoverDate.Month = dob.Month)
|> defaultArg <| false
Check.Quick (``age is near year difference`` badAge)
Check.Quick (``age is near year difference`` goodAge)
Check.Quick (``you are one year older on your birthday`` badAge)
Check.Quick (``you are one year older on your birthday`` goodAge)
// -----------------------------------------------
// enforce that dates are in past (if needed)
// -----------------------------------------------
let dateMustBeInPast (dob:System.DateTime) =
dob < System.DateTime.Today
let prop1 fnAge dob = (dateMustBeInPast dob ==> ``age is near year difference`` fnAge dob )
let prop2 fnAge dob = (dateMustBeInPast dob ==> ``you are one year older on your birthday`` fnAge dob )
Check.Quick (prop1 badAge)
Check.Quick (prop1 goodAge)
Check.Quick (prop2 badAge)
Check.Quick (prop2 goodAge)
@isaacabraham
Copy link

How about a function like person born one year later is one year younger which takes a single DOB, adds a year onto it and confirms that the results are 1 apart?

@swlaschin
Copy link
Author

Fixed bugs in gist!

@swlaschin
Copy link
Author

goodAge fails for some dates!

Falsifiable, after 84 tests (2 shrinks) (StdGen (1781193483,295947640)):
29/02/1972 02:00:00

@isaacabraham
Copy link

This could be a good start for a kata or something :-)

@isaacabraham
Copy link

I got it working in the end for leap years - the actual impl was fine, it is the property that needed changing for when someone's DOB is on feb 29 and the current year is not a leap year, it expected March 1st.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment