is there a more functionally idiomatic way of generating valid dates in f#? 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 -&gt; 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()) 
    |&gt; dateAttempt

let chooseValidDate d =
    match d with
    | WorkingDate d -&gt; Some d
    | _ -&gt; None

let sampleDobs = [for i in 1 .. 1000 -&gt; generateDate()]

let cleanDates = Seq.choose chooseValidDate sampleDobs
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 -&gt; generateBirthDate()]