Skip to content

Commit

Permalink
[Python] Fixes for datetime subtract (#3630)
Browse files Browse the repository at this point in the history
* Fixes for datetime subtract

* Fix error in days to microseconds calculation

* Fix constant casing

* Update changelog
  • Loading branch information
dbrattli authored Nov 30, 2023
1 parent d9da1d3 commit 308acef
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
51 changes: 42 additions & 9 deletions src/fable-library-py/fable_library/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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",
]
2 changes: 1 addition & 1 deletion src/fable-library-py/fable_library/time_span.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
27 changes: 27 additions & 0 deletions tests/Python/TestDateTime.fs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,33 @@ let ``test DateTime.MinValue works in pattern match`` () =
| Some date when date <> DateTime.MinValue -> ()
| _ -> failwith "expected pattern match above"

[<Fact>]
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

[<Fact>]
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


// [<Fact>]
// let ``test DateTime.ToLocalTime works`` () =
// let d = DateTime(2014, 10, 9, 13, 23, 30, DateTimeKind.Utc)
Expand Down

0 comments on commit 308acef

Please sign in to comment.