Skip to content

Native DateOnly to Python datetime.date#801

Open
buvinghausen wants to merge 4 commits intotonybaloney:mainfrom
buvinghausen:add_dateonly_date
Open

Native DateOnly to Python datetime.date#801
buvinghausen wants to merge 4 commits intotonybaloney:mainfrom
buvinghausen:add_dateonly_date

Conversation

@buvinghausen
Copy link
Copy Markdown
Contributor

Add DateOnlydatetime.date interop

Adds bidirectional conversion between C#'s DateOnly and Python's datetime.date.

Conversion approach

The conversion uses the ordinal day representation to avoid any string parsing, locale issues, or intermediate DateTime allocations — making it the cleanest and fastest round-trip.

  • C# → Python: date.DayNumber + 1 is passed to Python's date.fromordinal()
  • Python → C#: Python's date.toordinal() result minus 1 is passed to DateOnly.FromDayNumber()

The offset of 1 exists because C#'s DayNumber is zero-based (day 0 = January 1, 0001) while Python's ordinal is one-based (ordinal 1 = January 1, 0001).

Changes

Runtime (CSnakes.Runtime)

  • PyObjectTypeConverter.Date.cs — new partial class implementing ConvertFromDateOnly and ConvertToDateOnly via the ordinal approach
  • PyObject.cs — added PyObject.From(DateOnly) and PyObject.From(DateOnly?) factory overloads; As<DateOnly>() dispatch added to the type-switch
  • PyObjectImporters.cs — added [Experimental("PRTEXP001")] public sealed class Date : IPyObjectImporter<DateOnly>
  • PublicAPI.Unshipped.txt (net8.0 & net9.0) — new public surface area recorded

Source generation (CSnakes.SourceGeneration)

  • PythonTypeSpec.cs — added DateType singleton record (base("date"))
  • PythonParser.TypeDef.cs — parser maps "date" and "datetime.date" to DateType
  • TypeReflection.csDateType maps to the C# type name DateOnly
  • ResultConversionCodeGenerator.csDateType case wired to the Date scalar generator

Tests

  • CSnakes.Runtime.Tests/Converter/DateConverterTest.cs — round-trip unit tests via both obj.As<DateOnly>() and obj.ImportAs<DateOnly, PyObjectImporters.Date>() covering MinValue, MaxValue, Unix epoch, and a known date
  • CSnakes.Tests/TypeReflectionTests.cs — added ("date", "DateOnly") and ("datetime.date", "DateOnly") to the type reflection theory data
  • CSnakes.Tests/PythonTypeSpecTests.cs — added DateTypeTests and UuidTypeTests inner test classes; both singletons added to Singletons_AreExpectedTypes
  • CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_date.approved.txt — snapshot approval confirming DateOnly and global::CSnakes.Runtime.Python.PyObjectImporters.Date appear correctly in generated code
  • Integration.Tests/python/test_date.py — Python test module with test_date_roundtrip and test_create_date
  • Integration.Tests/DateTests.cs — integration tests: roundtrip for a known date, DateOnly.MinValue, and construction from year/month/day components

Example

# test_date.py
import datetime

def test_date_roundtrip(value: datetime.date) -> datetime.date:
    return value

def test_create_date(year: int, month: int, day: int) -> datetime.date:
    return datetime.date(year, month, day)
var module = env.TestDate();

DateOnly date = new DateOnly(2026, 3, 8);
DateOnly result = module.TestDateRoundtrip(date);   // round-trips through Python

DateOnly created = module.TestCreateDate(2026, 3, 8); // constructed in Python

Copilot AI review requested due to automatic review settings March 9, 2026 04:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds bidirectional conversion between C#'s DateOnly and Python's datetime.date, using ordinal-based conversion (avoiding string parsing or intermediate DateTime allocations). The implementation follows the established patterns for type conversion throughout the CSnakes codebase.

Changes:

  • Adds DateOnlydatetime.date conversion via ordinal representation (PyObjectTypeConverter.Date.cs), with PyObject.From(DateOnly) factory overloads and As<DateOnly>() dispatch in the runtime
  • Adds source generation support: DateType type spec, parser mapping for "date"/"datetime.date", C# type reflection to DateOnly, and result conversion code generation
  • Adds comprehensive tests: unit tests for round-trip conversion, source generation snapshot tests, type reflection tests, and integration tests

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/CSnakes.Runtime/PyObjectTypeConverter.Date.cs New partial class with ConvertFromDateOnly and ConvertToDateOnly using ordinal-based conversion
src/CSnakes.Runtime/Python/PyObject.cs Added From(DateOnly), From(DateOnly?) overloads and As<DateOnly>() dispatch
src/CSnakes.Runtime/Python/PyObjectImporters.cs Added Date importer class implementing IPyObjectImporter<DateOnly>
src/CSnakes.SourceGeneration/Parser/Types/PythonTypeSpec.cs Added DateType singleton record
src/CSnakes.SourceGeneration/Parser/PythonParser.TypeDef.cs Maps "date" and "datetime.date" to DateType
src/CSnakes.SourceGeneration/Reflection/TypeReflection.cs Maps DateType to DateOnly
src/CSnakes.SourceGeneration/ResultConversionCodeGenerator.cs Wires DateType to the scalar Date code generator
src/CSnakes.Runtime/PublicAPI/net8.0/PublicAPI.Unshipped.txt Records new public API surface (net8.0)
src/CSnakes.Runtime/PublicAPI/net9.0/PublicAPI.Unshipped.txt Records new public API surface (net9.0)
src/CSnakes.Runtime.Tests/Converter/DateConverterTest.cs Round-trip unit tests for DateOnly conversion
src/CSnakes.Tests/TypeReflectionTests.cs Adds date/datetime.dateDateOnly test cases
src/CSnakes.Tests/PythonTypeSpecTests.cs Adds DateTypeTests and singleton assertion
src/CSnakes.Tests/PythonStaticGeneratorTests/FormatClassFromMethods.test_date.approved.txt Snapshot approval for generated code
src/Integration.Tests/python/test_date.py Python test module for date round-trip and creation
src/Integration.Tests/DateTests.cs Integration tests for date conversion

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

buvinghausen and others added 3 commits March 9, 2026 00:29
Make optional work

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants