4
\$\begingroup\$
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
\$\endgroup\$
6
\$\begingroup\$

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()]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.