diff --git a/src/Hedgehog/Gen.fs b/src/Hedgehog/Gen.fs index 865bc49d..81f30bd8 100644 --- a/src/Hedgehog/Gen.fs +++ b/src/Hedgehog/Gen.fs @@ -515,21 +515,37 @@ module Gen = return System.Guid bs } - /// Generates a random instant in time expressed as a date and time of day. + /// Generates a random DateTime using the specified range. + /// For example: + /// let range = + /// Range.constantFrom + /// (System.DateTime (2000, 1, 1)) System.DateTime.MinValue System.DateTime.MaxValue + /// Gen.dateTime range [] - let dateTime : Gen = - let minTicks = - System.DateTime.MinValue.Ticks - let maxTicks = - System.DateTime.MaxValue.Ticks + let dateTime (range : Range) : Gen = gen { - let! ticks = - Range.constantFrom - (System.DateTime (2000, 1, 1)).Ticks minTicks maxTicks - |> integral + let! ticks = range |> Range.map (fun dt -> dt.Ticks) |> integral return System.DateTime ticks } + /// Generates a random DateTimeOffset using the specified range. + [] + let dateTimeOffset (range : Range) : Gen = + gen { + let! ticks = range |> Range.map (fun dt -> dt.Ticks) |> integral + // Ensure there is no overflow near the edges when adding the offset + let minOffsetMinutes = + max + (-14L * 60L) + ((DateTimeOffset.MaxValue.Ticks - ticks) / TimeSpan.TicksPerMinute * -1L) + let maxOffsetMinutes = + min + (14L * 60L) + ((ticks - DateTimeOffset.MinValue.Ticks) / TimeSpan.TicksPerMinute) + let! offsetMinutes = int (Range.linearFrom 0 (Operators.int minOffsetMinutes) (Operators.int maxOffsetMinutes)) + return System.DateTimeOffset(ticks, TimeSpan.FromMinutes (Operators.float offsetMinutes)) + } + // // Sampling // diff --git a/tests/Hedgehog.Tests/GenTests.fs b/tests/Hedgehog.Tests/GenTests.fs index 7c5314f7..88d7aefc 100644 --- a/tests/Hedgehog.Tests/GenTests.fs +++ b/tests/Hedgehog.Tests/GenTests.fs @@ -13,7 +13,7 @@ open Xunit [] [] let ``dateTime creates System.DateTime instances`` count = - let actual = Gen.dateTime |> Gen.sample 0 count + let actual = Gen.dateTime (Range.constant System.DateTime.MinValue System.DateTime.MaxValue) |> Gen.sample 0 count actual |> List.distinct |> List.length @@ -45,7 +45,7 @@ let ``dateTime randomly generates value between max and min ticks`` () = |> Random.run seed1 0 let expected = System.DateTime ticks - let actual = Gen.dateTime + let actual = Gen.dateTime (Range.constant System.DateTime.MinValue System.DateTime.MaxValue) let result = actual |> Gen.toRandom |> Random.run seed0 0 |> Tree.outcome expected =! result @@ -54,7 +54,9 @@ let ``dateTime randomly generates value between max and min ticks`` () = let ``dateTime shrinks to correct mid-value`` () = let result = property { - let! actual = Gen.dateTime + let! actual = + Range.constantFrom (System.DateTime (2000, 1, 1)) System.DateTime.MinValue System.DateTime.MaxValue + |> Gen.dateTime System.DateTime.Now =! actual } |> Property.report