Skip to content

Add support for Date/TimeOnly to STJ #51302

Closed

Description

@devsko

Background and Motivation

The recently added types DateOnly and TimeOnly should be fully supported by System.Text.Json. Even when it's possible to make them serializable via a built-in or custom converter, adding support to Utf8JsonReader/Writer brings them on par with other types like DateTimeOffset.

Proposed API

namespace System.Text.Json
{
    public ref partial struct Utf8JsonReader
    {
+        public DateOnly GetDateOnly();
+        public TimeOnly GetTimeOnly();
+        public bool TryGetDateOnly(out DateOnly value);
+        public bool TryGetTimeOnly(out TimeOnly value);
    }

    public sealed partial class Utf8JsonWriter
    {
+        public void WriteString(JsonEncodedText propertyName, DateOnly value);
+        public void WriteString(JsonEncodedText propertyName, TimeOnly value);
+        public void WriteString(string propertyName, DateOnly value);
+        public void WriteString(string propertyName, TimeOnly value);
+        public void WriteString(ReadOnlySpan<char> propertyName, DateOnly value);
+        public void WriteString(ReadOnlySpan<char> propertyName, TimeOnly value);
+        public void WriteString(ReadOnlySpan<byte> utf8PropertyName, DateOnly value);
+        public void WriteString(ReadOnlySpan<byte> utf8PropertyName, TimeOnly value);
+        public void WriteStringValue(DateOnly value);
+        public void WriteStringValue(TimeOnly value);
    }

    public readonly partial struct JsonElement
    {
+        public DateOnly GetDateOnly();
+        public TimeOnly GetTimeOnly();
+        public bool TryGetDateOnly(out DateOnly value)
+        public bool TryGetTimeOnly(out TimeOnly value)
    }
}

namespace System.Text.Json.Node
{
    public abstract partial class JsonNode
    {
+        public static explicit operator DateOnly(JsonNode value);
+        public static explicit operator TimeOnly(JsonNode value);
+        public static explicit operator DateOnly?(JsonNode? value);
+        public static explicit operator TimeOnly?(JsonNode? value);
+        public static implicit operator JsonNode(DateOnly value);
+        public static implicit operator JsonNode(TimeOnly value);
+        public static implicit operator JsonNode?(DateOnly? value);
+        public static implicit operator JsonNode?(TimeOnly? value);
    }
}

namespace System.Text.Json.Serialization.Metadata
{
    public static partial class JsonMetadataServices
    {
+        public static JsonConverter<DateOnly> DateOnlyConverter { get; }
+        public static JsonConverter<TimeOnly> TimeOnlyConverter { get; }
    }
}

namespace System.Buffers.Text
{
    public static partial class Utf8Formatter
    {
+        public static bool TryFormat(DateOnly value, Span<byte> destination, out int bytesWritten, StandardFormat format = default);
+        public static bool TryFormat(TimeOnly value, Span<byte> destination, out int bytesWritten, StandardFormat format = default);
    }
    public static partial class Utf8Parser
    {
+        public static bool TryParse(ReadOnlySpan<byte> source, out DateOnly value, out int bytesConsumed, char standardFormat = default);
+        public static bool TryParse(ReadOnlySpan<byte> source, out TimeOnly value, out int bytesConsumed, char standardFormat = default);
    }
}

Usage Examples

    var value = reader.GetDateOnly();
    writer.WriteStringValue(value);

Alternative Designs

As mentioned it would be possible to just add serialization converters for these types without supporting the Utf8Reader/Writer scenarios.

Risks

Obviously this API cannot be added to platforms prior .NET 6. Thus it would be necessary to only include it in the .NET 6 version of STJ.

Updates

  • Added Utf8Formatter.TryFormat and Utf8Parser.TryParse overloads.

Activity

  1. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Apr 15, 2021
  2. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 15, 2021
  3. eiriktsarpalis commented on Apr 15, 2021

    @eiriktsarpalis
    Member

    Tagging @layomia and @steveharter for thoughts. It stands to reason that we should aim to release support for the new types in .NET 6 (presumably conforming to ISO 8601 date only/time only formats).

  4. devsko commented on Apr 15, 2021

    @devsko
    ContributorAuthor

    A small collection of ISO 8601 related issues:

  5. devsko commented on Apr 16, 2021

    @devsko
    ContributorAuthor

    IMO the formatting/parsing of the new types should be implemented identically as for DateTime(Offset) (and TimeSpan). Any changes wrt ISO 8601 are orthogonal and should be applied to all of these types in the same way.

  6. added this to the Future milestone on Apr 19, 2021
  7. mattjohnsonpint commented on May 7, 2021

    @mattjohnsonpint
    Contributor

    I agree these should have full parity with the other date/time types.

    In the meantime, here's some simple converters that will do the trick. (Though ultimately, they should not be needed.)

    public class DateOnlyJsonConverter : JsonConverter<DateOnly>
    {
        private const string DateFormat = "yyyy-MM-dd";
    
        public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateOnly.ParseExact(reader.GetString(), DateFormat, CultureInfo.InvariantCulture);
        }
    
        public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString(DateFormat, CultureInfo.InvariantCulture));
        }
    }
    
    public class TimeOnlyJsonConverter : JsonConverter<TimeOnly>
    {
        private const string TimeFormat = "HH:mm:ss.FFFFFFF";
    
        public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return TimeOnly.ParseExact(reader.GetString(), TimeFormat, CultureInfo.InvariantCulture);
        }
    
        public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString(TimeFormat, CultureInfo.InvariantCulture));
        }
    }
  8. ericstj commented on May 25, 2021

    @ericstj
    Member

    cc @tarekgh - should we look for elsewhere in the framework that has special handling for DateTime/DateTimeOffset and ensure we add handling for DateOnly/TimeOnly as well?

  9. tarekgh commented on May 25, 2021

    @tarekgh
    Member

    should we look for elsewhere in the framework that has special handling for DateTime/DateTimeOffset and ensure we add handling for DateOnly/TimeOnly as well?

    @ericstj yes this is in our radar but not really planned for 6.0 release. It would be good candidate for 7.0 release. If we get a chance before then we should consider it.

  10. layomia commented on Jun 1, 2021

    @layomia
    Contributor

    We likely won't get to this level of support in .NET 6.0, but can support them in JsonSerializer now - #53539.

  11. LaughingJohn commented on Aug 2, 2021

    @LaughingJohn

    Are XmlSerializer and DataContractSerializer also going to be supported?

  12. eiriktsarpalis commented on Aug 2, 2021

    @eiriktsarpalis
    Member

    @LaughingJohn I created a separate issue on that question to be considered by the area owners of those serializers.

  13. LaughingJohn commented on Aug 2, 2021

    @LaughingJohn
  14. eiriktsarpalis commented on Oct 22, 2021

    @eiriktsarpalis
    Member

    Closing in favor of #53539.

  15. ghost locked as resolved and limited conversation to collaborators on Nov 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions