diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index 8e4964af27..77bf6c8ea2 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fix #3598: Using obj () now generated an empty dict instead of None * Fix #3597: Do not translate .toString methods to str * Fix #3610: Cleanup Python regex handling +* Fix #3628: System.DateTime.Substract not correctly transpiled ## 4.6.0 - 2023-11-27 diff --git a/src/fable-library-py/fable_library/date.py b/src/fable-library-py/fable_library/date.py index ec9775bdc3..de79fcbffe 100644 --- a/src/fable-library-py/fable_library/date.py +++ b/src/fable-library-py/fable_library/date.py @@ -5,21 +5,28 @@ from re import Match from typing import Any -from .time_span import TimeSpan +from .time_span import TimeSpan, total_microseconds from .time_span import create as create_time_span from .types import FSharpRef from .util import DateKind -formatRegExp = re.compile(r"(\w)\1*") +FORMAT_REGEXP = re.compile(r"(\w)\1*") -def op_subtraction(x: datetime, y: datetime) -> TimeSpan: - delta = x - y - # ts.microseconds only contains the microseconds provided to the constructor - # so we need to calculate the total microseconds ourselves - delta_microseconds = delta.days * (24 * 3600) + delta.seconds * 10**6 + delta.microseconds - return create_time_span(0, 0, 0, 0, 0, delta_microseconds) +def subtract(x: datetime, y: datetime | TimeSpan) -> datetime | TimeSpan: + if isinstance(y, datetime): + delta = x - y + # ts.microseconds only contains the microseconds provided to the constructor + # so we need to calculate the total microseconds ourselves + delta_microseconds = delta.days * (24 * 3600 * 10**6) + delta.seconds * 10**6 + delta.microseconds + return create_time_span(0, 0, 0, 0, 0, delta_microseconds) + + return x - timedelta(microseconds=total_microseconds(y)) + + +def op_subtraction(x: datetime, y: datetime | TimeSpan) -> datetime | TimeSpan: + return subtract(x, y) def create( @@ -79,7 +86,7 @@ def match(match: Match[str]) -> str: return group - ret = formatRegExp.sub(match, format) + ret = FORMAT_REGEXP.sub(match, format) return ret # return format.replace(/(\w)\1*/g, (match) => { @@ -228,3 +235,29 @@ def try_parse(string: str, style: int, unsigned: bool, bitsize: int, defValue: F return True except Exception: return False + + +def add_milliseconds(d: datetime, v: int) -> datetime: + return d + timedelta(milliseconds=v) + + +__all__ = [ + "op_subtraction", + "subtract", + "create", + "year", + "date_to_string_with_custom_format", + "date_to_string_with_offset", + "date_to_string_with_kind", + "to_string", + "now", + "utc_now", + "to_local_time", + "compare", + "equals", + "max_value", + "min_value", + "op_addition", + "parse", + "try_parse", +] diff --git a/src/fable-library-py/fable_library/time_span.py b/src/fable-library-py/fable_library/time_span.py index c168412415..ece50c617b 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 math import ceil, floor, fmod 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 diff --git a/tests/Python/TestDateTime.fs b/tests/Python/TestDateTime.fs index 0a1fe5ee85..85a70568f0 100644 --- a/tests/Python/TestDateTime.fs +++ b/tests/Python/TestDateTime.fs @@ -74,6 +74,33 @@ let ``test DateTime.MinValue works in pattern match`` () = | Some date when date <> DateTime.MinValue -> () | _ -> failwith "expected pattern match above" +[] +let ``test DateTime Subtraction with TimeSpan works`` () = + let test ms expected = + let dt = DateTime(2014,9,12,0,0,0,DateTimeKind.Utc) + let ts = TimeSpan.FromMilliseconds(ms) + let res1 = dt.Subtract(ts) |> thatYearSeconds + let res2 = (dt - ts) |> thatYearSeconds + equal true (res1 = res2) + equal expected res1 + test 1000. 21945599.0 + test -1000. 21945601.0 + test 0. 21945600.0 + +[] +let ``test DateTime Subtraction with DateTime works`` () = + let test ms expected = + let dt1 = DateTime(2014, 10, 9, 13, 23, 30, 234, DateTimeKind.Utc) + let dt2 = dt1.AddMilliseconds(ms) + let res1 = dt1.Subtract(dt2).TotalSeconds + let res2 = (dt1 - dt2).TotalSeconds + equal true (res1 = res2) + equal expected res1 + test 1000. -1.0 + test -1000. 1.0 + test 0. 0.0 + + // [] // let ``test DateTime.ToLocalTime works`` () = // let d = DateTime(2014, 10, 9, 13, 23, 30, DateTimeKind.Utc)