open System
type Date = System.DateTime
type SafeDate =
| WorkingDate of Date
| InvalidDate of Exception
let dateAttempt (x: int, y:int, z:int) =
try
let returnDate = Date(z,y,x)
WorkingDate returnDate
with
ex -> InvalidDate ex
let rnd = System.Random(4)
let randomBirthYear() =
rnd.Next(1904,1954)
let randomBirthMonth() =
rnd.Next(1,13)
let randomBirthDay() =
rnd.Next(1,32)
let generateDate() =
(randomBirthDay(), randomBirthMonth(), randomBirthYear())
|> dateAttempt
let chooseValidDate d =
match d with
| WorkingDate d -> Some d
| _ -> None
let sampleDobs = [for i in 1 .. 1000 -> generateDate()]
let cleanDates = Seq.choose chooseValidDate sampleDobs
1 Answer
One way to work around invalid dates is not to generate them in the first place: find the number of days between the boundary dates, generate a random integer from this range and then add that number of days to the start date:
let generateDate (min : Date) max =
let totalDays = int (max - min).TotalDays
let generatedDays = rnd.Next(0, totalDays)
let generatedDate = min.AddDays(float generatedDays)
generatedDate
let generateDateByYear minYear maxYear =
generateDate (Date(minYear, 1, 1)) (Date(maxYear, 1, 1))
let generateBirthDate() = generateDateByYear 1904 1954
let sampleDobs = [for i in 1 .. 1000 -> generateBirthDate()]