From 64c53c5c35113b80ede20ecd822221d1802d83f5 Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Wed, 22 Nov 2023 22:41:55 +0100 Subject: [PATCH] Fix negative TimeSpan support --- .../fable_library/time_span.py | 21 ++--- src/quicktest-py/quicktest.fsx | 90 +------------------ 2 files changed, 13 insertions(+), 98 deletions(-) diff --git a/src/fable-library-py/fable_library/time_span.py b/src/fable-library-py/fable_library/time_span.py index 80826c693c..a9c392cfbf 100644 --- a/src/fable-library-py/fable_library/time_span.py +++ b/src/fable-library-py/fable_library/time_span.py @@ -1,9 +1,9 @@ from __future__ import annotations -from datetime import timedelta from typing import Any from .util import pad_left_and_right_with_zeros, pad_with_zeros +from math import fmod, ceil, floor # TimeSpan is represented as an int which is the Tick value @@ -105,27 +105,28 @@ def ticks(ts: TimeSpan) -> int: def microseconds(ts: TimeSpan) -> int: - return int(ts % 10000 / 10) + return int(fmod(ts, 10000) / 10) def milliseconds(ts: TimeSpan) -> int: - return int(ts % 10000000 / 10000) + return int(fmod(ts, 10000000) / 10000) def seconds(ts: TimeSpan) -> int: - return int(ts % 600000000 / 10000000) + return int(fmod(ts, 600000000) / 10000000) def minutes(ts: TimeSpan) -> int: - return int(ts % 36000000000 / 600000000) + return int(fmod(ts, 36000000000) / 600000000) def hours(ts: TimeSpan) -> int: - return int(ts % 864000000000 / 36000000000) + return int(fmod(ts, 864000000000) / 36000000000) def days(ts: TimeSpan) -> int: - return int(ts / 864000000000) + res = ts / 864000000000 + return ceil(res) if res < 0 else floor(res) def negate(ts: TimeSpan) -> TimeSpan: @@ -159,9 +160,9 @@ def to_string(ts: TimeSpan, format: str = "c", _provider: Any | None = None) -> raise ValueError("Custom formats are not supported") d = abs(days(ts)) - h = hours(ts) - m = minutes(ts) - s = seconds(ts) + h = abs(hours(ts)) + m = abs(minutes(ts)) + s = abs(seconds(ts)) ms = abs(milliseconds(ts)) sign: str = "-" if ts < 0 else "" diff --git a/src/quicktest-py/quicktest.fsx b/src/quicktest-py/quicktest.fsx index db04641c6a..974b9a53f7 100644 --- a/src/quicktest-py/quicktest.fsx +++ b/src/quicktest-py/quicktest.fsx @@ -7,7 +7,8 @@ open Fable.Python.Builtins open System let equal expected actual = - Assert.AreEqual(expected, actual) + // According the console log arguments are reversed + Assert.AreEqual(actual, expected) [] let main argv = @@ -18,91 +19,4 @@ let main argv = // use file = builtins.``open``(StringPath "data.txt") // file.read() |> printfn "File contents: %s" - let t1 = TimeSpan(10, 10, 10) - let t2 = TimeSpan(1, 1, 1, 1, 1, 1) - let t3 = TimeSpan(1, 1, 1, 1, 1) - - // printfn "%A" t1.TotalSeconds - // printfn "%A" t2.TotalSeconds - // printfn "%A" t3.TotalMilliseconds - - // printfn "%A" t3.TotalMicroseconds - // printfn "%A" t3.TotalMilliseconds - // printfn "%A" t3.TotalSeconds - // printfn "%A" t3.TotalMinutes - // printfn "%A" t3.TotalHours - // printfn "%A" t3.TotalDays - // printfn "%A" 1.042372697 - // printfn "%A" (t3.TotalDays = 1.042372697) - - // TimeSpan(10, 20, 30, 10, 10, 10).Ticks |> printfn "TotalMicroseconds: %A" - // TimeSpan(10, 20, 30, 10, 5, 12).Milliseconds |> printfn "TotalMicroseconds: %A" - // TimeSpan(10, 20, 30, 10, -5, 12).Milliseconds |> printfn "TotalMicroseconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).Milliseconds |> printfn "Milliseconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).Seconds |> printfn "Seconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).Minutes |> printfn "Minutes: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).Hours |> printfn "Hours: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).Days |> printfn "TotalDays: %A" - - // TimeSpan(10, 0, 0, 0, 0).Divide(3.26).Ticks |> printfn "TotalMicroseconds: %A" - - // TimeSpan.FromTicks(2650306748466L).TotalSeconds |> printfn "TotalSeconds: %A" - - // TimeSpan(1).TotalNanoseconds |> printfn "TotalNanoseconds: %A" - // TimeSpan(1).Ticks |> printfn "Ticks: %A" - // TimeSpan.FromHours(3).TotalHours |> printfn "TotalHours: %A" - // TimeSpan.FromHours(3).Hours |> printfn "TotalHours: %A" - // TimeSpan(0,3,0,0,0).Hours |> printfn "TotalHours: %A" - - // TimeSpan.fro - - // TimeSpan(10, 20, 30, 10, 10, 10).TotalMicroseconds.ToString() |> printfn "TotalMicroseconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).TotalMilliseconds.ToString() |> printfn "TotalMilliseconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).TotalSeconds.ToString() |> printfn "TotalSeconds: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).TotalMinutes.ToString() |> printfn "TotalMinutes: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).TotalHours.ToString() |> printfn "TotalHours: %A" - // TimeSpan(10, 20, 30, 10, 10, 10).TotalDays.ToString() |> printfn "TotalDays: %A" - - // TimeSpan(10, 20, 30, 10, 10, 10).Ticks.ToString() |> printfn "TotalDays: %A" - - // printfn "%A" (TimeSpan(10, 20, 30, 10, 10, 10).TotalMicroseconds = 9.3781001e+11) - - // printfn "%A" 9.3781001e+11 - - // TimeSpan(10, 20, 30, 10, 10, 10).TotalDays |> printfn "%A" - // printfn "%A" 10.85428252 - - - async { - let mutable _aggregate = 0 - - let makeWork i = - async { - // check that the individual work items run sequentially and not interleaved - _aggregate <- _aggregate + i - let copyOfI = _aggregate - do! Async.Sleep 100 - equal copyOfI _aggregate - do! Async.Sleep 100 - equal copyOfI _aggregate - return i - } - let works = [ for i in 1 .. 5 -> makeWork i ] - let now = DateTimeOffset.Now - let! result = Async.Sequential works - let ``then`` = DateTimeOffset.Now - let d = ``then`` - now - if d.TotalSeconds < 0.99 then - failwithf "expected sequential operations to take 1 second or more, but took %.3f" d.TotalSeconds - result |> equal [| 1 .. 5 |] - result |> Seq.sum |> equal _aggregate - } |> Async.RunSynchronously - - - - - 0 - - // .NET: 10.85428252 - // Python (best precision): 10.854282523263889