Skip to content

[API Proposal]: Utf8JsonReader DateTimeOffset TimeZone Overloads #105583

Closed as not planned
@RyanThomas73

Description

@RyanThomas73

Background and motivation

The System.Text.Json base class library has support for efficient reading of DateTime and DateTimeOffset types.

However these implementations currently all fallback to assuming the DateTime/DateTimeOffset should be constructed as DateTimeKind.Local if the json token does not include the "Z" suffix or an explicit timezone offset. See JsonHelpers.TryParseAsISO

It would be advantageous for developers if these methods, such as Utf8Reader.TryGetDateTimeOffset were overloaded such that the developer can supply an explicit time zone offset to fallback on if the json token does not include the time zone.

One example usage would be a custom JsonConverter that wishes to use Utf8Reader.TryGetDateTimeOffset for efficiency as described in the microsoft docs here. Currently, if the developer needed such a converter to use an explicit offset as the fallback, they would be forced to use a less efficient option of reading the token as a string and then parsing it explicitly after the fact.

API Proposal

namespace System.Text.Json;

public ref partial struct Utf8JsonReader
{
    /// <summary>
    /// Parses the current JSON token value from the source as a <see cref="DateTimeOffset"/>.
    /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully
    /// parsed to a <see cref="DateTimeOffset"/> value.
    /// Returns <see langword="false"/> otherwise.
    /// </summary>
    /// <param name="fallbackTimezoneOffset">An explicit offset from Coordinated Universal Time (UTC) to use for the <see cref="DateTimeOffset"/> output if the token value does not explicitly included the time zone information.</param>
    /// <exception cref="InvalidOperationException">
    /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>.
    /// <seealso cref="TokenType" />
    /// </exception>
    public bool TryGetDateTimeOffset(ref TimeSpan fallbackTimezoneOffset, out DateTimeOffset value)
    {
        if (TokenType != JsonTokenType.String)
        {
            ThrowHelper.ThrowInvalidOperationException_ExpectedString(TokenType);
        }

        return TryGetDateTimeOffsetCore(fallbackTimezoneOffset, out value);
    }
}

Similar methods in the System.Text.Json namespace such as JsonElement.(Try)GetDateTimeOffset would also benefit from such an overload.

API Usage

public class DateTimeOffsetConverterThatAssumesUtcIfNoTimeZoneIsEncoded : JsonConverter<DateTimeOffset>
{
    public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (!reader.TryGetDateTimeOffset(TimeSpan.Zero, out var value))
        {
            value = DateTimeOffset.Parse(reader.GetString(), null, System.Globalization.DateTimeStyles.AssumeUniversal);
        }
        
        return value;
    }
}

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions