The types `DateOnly` and `TimeOnly` do not get XAML serialized
Description
Variables of types DateOnly and TimeOnly do not get serialized when converted to XAML. This is not the case for other date-related standard types like DateTime or DateTimeOffset.
Reproduction Steps
Run the following function in a NET8 environment:
public void TestSerializationForDateTimeOnly()
{
var dateOnly = new DateOnly(2025, 3, 7);
var s1 = XamlServices.Save(dateOnly);
Console.WriteLine(s1);
var timeOnly = new TimeOnly(21, 49, 3);
var s2 = XamlServices.Save(timeOnly);
Console.WriteLine(s2);
var dateTime = new DateTime(dateOnly, timeOnly, DateTimeKind.Utc);
var s3 = XamlServices.Save(dateTime);
Console.WriteLine(s3);
}
Expected behavior
Variables of type DateOnly and TimeOnly should be correctly serialized by XamlServices.Save(...).
Actual behavior
After running the function, notice that:
s1is<?xml version="1.0"?> <DateOnly xmlns="clr-namespace:System;assembly=System.Private.CoreLib"/>s2is<?xml version="1.0"?> <TimeOnly xmlns="clr-namespace:System;assembly=System.Private.CoreLib"/>- However
s3is<?xml version="1.0"?> <DateTime xmlns="clr-namespace:System;assembly=System.Private.CoreLib">2025-03-07T21:49:03Z</DateTime>
Regression?
As far as we know this is not a regression.
Known Workarounds
We have found no workaround so far. We have attempted to follow the steps from https://learn.microsoft.com/en-us/dotnet/desktop/xaml-services/define-custom-types and define custom converters for DateOnly and TimeOnly and then used TypeDescriptor.AddAttribute(...) in order to map the converter to each of the types, but XAML serialization still did not occur. Also, we noticed that the converter DateTimeConverter2 exists in System.Xaml which probably explains why DateTime does get serialized correctly.
Impact
No response
Configuration
OS: Windows 11 on an x64 CPU NET version: 8.0
Other information
No response
There is two serializers, System.Xaml.XamlServices.Save and the "original" System.Windows.Markup.XamlWriter.Save.
Normally, the correct way is to supply ValueSerializer (rather than TypeSerializer) as you are not really serializing a type into string, just its value. This works for the original serializer. However, it looks like the System.Xaml.Schema.TypeReflector is not using TypeDescriptor but reflection directly and I would consider this a breaking change from the previous serializer. I would support updating the newer XAML services to use TypeDescriptor.
As a workaround for the new serializer, you can define your own XamlSchemaContext with your XamlType.
Edit: Note that the original serializer does not support DateTimeOffset which is slightly concerning.
Indeed, we have noticed as well that the information from TypeDescriptor is ignored by the "new" serializer, System.Xaml.XamlServices.Save(). Having said that, there should be no difference between how the types DateOnly / TimeOnly and the types DateTime / DateTimeOffset are treated by the serializer, given that they are all related. The fact that they are treated differently should be considered a bug. In the mean time, we will investigate the possibility of using a custom XamlSchemaContext as you've suggested.