Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API Proposal]: Utf8JsonReader DateTimeOffset TimeZone Overloads #105583

Closed
RyanThomas73 opened this issue Jul 27, 2024 · 7 comments
Closed

[API Proposal]: Utf8JsonReader DateTimeOffset TimeZone Overloads #105583

RyanThomas73 opened this issue Jul 27, 2024 · 7 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json

Comments

@RyanThomas73
Copy link
Contributor

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

@RyanThomas73 RyanThomas73 added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jul 27, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Jul 27, 2024
@eiriktsarpalis
Copy link
Member

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.

Utf8JsonReader includes the CopyString methods that make it possible to read from JSON strings without incurring additional allocations. Our built-in converters use that method and generally we've been resisting the temptation to bolt on more serialization-like features to the core reader type.

@RyanThomas73
Copy link
Contributor Author

we've been resisting the temptation to bolt on more serialization-like features to the core reader type.

I see. I was hoping to avoid needing to copy and duplicate all of the logic inside the JsonHelpers methods. But if the runtime team feels this is an area where it's really important to try and minimize the API surface area and complexity, then I suppose a much larger % of the developer community would need to advocate for a use case such as this to justify it.

A much broader scoped alternative for the need to copy/paste a lot of internal runtime code for relatively small changes would be to do something akin to what dotnet/efcore does - begin exposing parts of the internal runtime surface area with the public accessibility modifier and instead provided a roslyn analzyer that developers need to suppress to indicate that they understand the signatures are intended for internal use, may change at anytime, and they use them at their own risk.

The latter option would likely serve both objectives - it would keep the official public API surface area smaller while allowing developers with advanced use cases to judiciously identify some areas where they can keep their own total lines of code to maintain down with some selective re-use.

@RyanThomas73
Copy link
Contributor Author

Closing based on Eirik's response above.

@RyanThomas73 RyanThomas73 closed this as not planned Won't fix, can't repro, duplicate, stale Jul 27, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Jul 27, 2024
@eiriktsarpalis
Copy link
Member

eiriktsarpalis commented Jul 27, 2024

A much broader scoped alternative for the need to copy/paste a lot of internal runtime code for relatively small changes would be to do something akin to what dotnet/efcore does - begin exposing parts of the internal runtime surface area with the public accessibility modifier and instead provided a roslyn analzyer that developers need to suppress to indicate that they understand the signatures are intended for internal use, may change at anytime, and they use them at their own risk.

I'm not sure I follow, what APIs would you like to see exposed that aren't available today?

Closing based on Eirik's response above.

Even though Utf8JsonReader might not be the appropriate layer to include TZ support, that doesn't mean we couldn't consider doing this at the JsonSerializer/JsonConverter layer at some point.

@RyanThomas73
Copy link
Contributor Author

I'm not sure I follow, what APIs would you like to see exposed that aren't available today?

I was commenting on the amount of lines of internal code that I would need to duplicate - for example in my hypothetical json converter shown in the API Usage example - to achieve the same relatively high performance code using the CopyString method as you described it.

i.e.

It would simply be a nice to have, if we we're able to find a better balance between the important objective of keeping the runtime/BCL public api surface area small while also allowing developers with more advanced use cases ways to leverage some of that internal code in lieu of duplicating and increasing their own # of lines of code to maintain.

@eiriktsarpalis
Copy link
Member

The built-in date parser in STJ is mostly a polyfill of the implementation available in the Utf8Parser class. In fact I think we have an issue somewhere about eventually replacing the bespoke parsing implementation in STJ and use the publicly available UTF-8 parsers.

@eiriktsarpalis
Copy link
Member

#84305

@github-actions github-actions bot locked and limited conversation to collaborators Aug 31, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json
Projects
None yet
Development

No branches or pull requests

2 participants