Skip to content

Implement missing DateTimeOffset functionality for the Python target #4475

Description

@ncave

[Python] Implement missing DateTimeOffset members

Summary

The Python target's DateTimeOffset implementation in fable_library/date_offset.py is incomplete. Many members from System.DateTimeOffset either throw at runtime (referenced in Replacements.fs but not implemented in the library) or are silently missing.

Currently working

  • Constructor: DateTimeOffset(year, month, day, hour, minute, second, millisecond, offset) via create
  • Properties: Year, Month, Day, Hour, Minute, Second, Offset, DateTime, Now, UtcNow
  • Static fields: MinValue
  • Methods: ToString, TryParse, FromUnixTimeMilliseconds, FromUnixTimeSeconds, ToUnixTimeMilliseconds, ToUnixTimeSeconds
  • Operator: op_subtraction (DateTimeOffset - DateTimeOffset → TimeSpan, DateTimeOffset - TimeSpan → DateTimeOffset)
  • Equality/comparison: delegated to date.equals / date.compare

Missing / broken

Constructors

  • DateTimeOffset(DateTime)fromDate referenced in Replacements.fs but missing in date_offset.py
  • DateTimeOffset(Int64 ticks, TimeSpan offset)fromTicks referenced but missing
  • DateTimeOffset(DateOnly, TimeOnly, TimeSpan) — not handled

Fields

  • MaxValuedate_offset.maxValue referenced in Replacements.fs but missing in date_offset.py
  • UnixEpoch

Properties

  • UtcDateTimeto_universal_time referenced but missing
  • LocalDateTimeto_local_time referenced but missing
  • UtcTicksgetUtcTicks referenced but missing
  • Date (date-only component as DateTime)
  • DayOfWeek
  • DayOfYear
  • Millisecond
  • Microsecond
  • Nanosecond
  • Ticks (clock time ticks)
  • TimeOfDay (as TimeSpan)
  • TotalOffsetMinutes

Methods

  • Add(TimeSpan) — would go via catch-all to date_offset.add, which is missing
  • AddDays(float) — catch-all, not implemented
  • AddHours(float) — catch-all, not implemented
  • AddMicroseconds(float) — catch-all, not implemented
  • AddMilliseconds(float) — referenced as addMilliseconds (used for AddTicks), missing
  • AddMinutes(float) — catch-all, not implemented
  • AddMonths(int) — catch-all, not implemented
  • AddSeconds(float) — catch-all, not implemented
  • AddYears(int) — catch-all, not implemented
  • AddTicks(int64) — dispatches to addMilliseconds, which is missing
  • Compare(DateTimeOffset, DateTimeOffset) — static method, not handled
  • EqualsExact(DateTimeOffset) — not handled
  • FromFileTime(int64) — not handled
  • ToFileTime() — not handled
  • ToLocalTime()to_local_time referenced but missing
  • ToOffset(TimeSpan) — not handled
  • ToUniversalTime()to_universal_time referenced but missing
  • ParseExact — not handled
  • TryParseExact — not handled

Operators

  • op_addition (DateTimeOffset + TimeSpan) — commented out in Rust extension, missing in date_offset.py

Other

  • GetHashCode / hash support — Replacements.fs routes to date.dateHash, which does not exist in date.py; DateTimeOffset values cannot be used as map/set keys reliably

Implementation notes

  • The catch-all branch in Replacements.fs (line ~3022) forwards unknown instance methods to date_offset.<lowerFirst(methodName)>, so many Add* methods will silently try to call missing functions at runtime.
  • to_local_time and to_universal_time should return DateTimeOffset (not DateTime), consistent with the .NET API.
  • AddTicks is currently mapped to addMilliseconds(ticks / 10000) — this function needs to be added, and the mapping should be verified for precision.
  • Equality semantics: .NET compares DateTimeOffset by UTC-normalized instant (not by local time + offset pair). The current delegation to date.equals needs to apply the offset before comparing.
  • The Rust extension (src/fable-library-py/src/datetime_offset.rs) has stubs for most functions commented out — these should be completed when the Python implementation is stabilized.

Files to change

  • src/fable-library-py/fable_library/date_offset.py — main implementation
  • src/Fable.Transforms/Python/Replacements.fs — wire up new functions
  • tests/Python/TestDateTimeOffset.fs — add test coverage for each implemented member

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions