< Summary

Information
Class: RaidLoop.Core.Contracts.FlexibleNullableDateTimeOffsetJsonConverter
Assembly: RaidLoop.Core
File(s): /home/runner/work/RaidLoop/RaidLoop/src/RaidLoop.Core/Contracts/FlexibleDateTimeOffsetJsonConverter.cs
Line coverage
40%
Covered lines: 6
Uncovered lines: 9
Coverable lines: 15
Total lines: 96
Line coverage: 40%
Branch coverage
40%
Covered branches: 4
Total branches: 10
Branch coverage: 40%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Read(...)50%12860%
Write(...)0%620%

File(s)

/home/runner/work/RaidLoop/RaidLoop/src/RaidLoop.Core/Contracts/FlexibleDateTimeOffsetJsonConverter.cs

#LineLine coverage
 1using System.Globalization;
 2using System.Text.Json;
 3using System.Text.Json.Serialization;
 4
 5namespace RaidLoop.Core.Contracts;
 6
 7public sealed class FlexibleDateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset>
 8{
 9    internal static readonly string[] LegacyUtcFormats =
 10    [
 11        "yyyy-MM-dd HH:mm:ss.FFFFFF",
 12        "yyyy-MM-dd HH:mm:ss.FFFFFFF",
 13        "yyyy-MM-dd HH:mm:ss"
 14    ];
 15
 16    public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 17    {
 18        if (reader.TokenType != JsonTokenType.String)
 19        {
 20            throw new JsonException($"Expected string token when parsing {nameof(DateTimeOffset)}.");
 21        }
 22
 23        var value = reader.GetString();
 24        if (string.IsNullOrWhiteSpace(value))
 25        {
 26            throw new JsonException("Timestamp string was null or empty.");
 27        }
 28
 29        if (TryParseFlexible(value, out var parsed))
 30        {
 31            return parsed;
 32        }
 33
 34        throw new JsonException($"Unable to parse DateTimeOffset value '{value}'.");
 35    }
 36
 37    public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
 38    {
 39        writer.WriteStringValue(value.ToUniversalTime().ToString("O", CultureInfo.InvariantCulture));
 40    }
 41
 42    internal static bool TryParseFlexible(string value, out DateTimeOffset parsed)
 43    {
 44        if (DateTimeOffset.TryParseExact(
 45                value,
 46                LegacyUtcFormats,
 47                CultureInfo.InvariantCulture,
 48                DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
 49                out parsed))
 50        {
 51            return true;
 52        }
 53
 54        return DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out parsed);
 55    }
 56}
 57
 58public sealed class FlexibleNullableDateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset?>
 59{
 60    public override DateTimeOffset? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 61    {
 162        if (reader.TokenType == JsonTokenType.Null)
 63        {
 064            return null;
 65        }
 66
 167        if (reader.TokenType != JsonTokenType.String)
 68        {
 069            throw new JsonException($"Expected string token when parsing {nameof(DateTimeOffset)}.");
 70        }
 71
 172        var value = reader.GetString();
 173        if (string.IsNullOrWhiteSpace(value))
 74        {
 075            return null;
 76        }
 77
 178        if (FlexibleDateTimeOffsetJsonConverter.TryParseFlexible(value, out var parsed))
 79        {
 180            return parsed;
 81        }
 82
 083        throw new JsonException($"Unable to parse DateTimeOffset value '{value}'.");
 84    }
 85
 86    public override void Write(Utf8JsonWriter writer, DateTimeOffset? value, JsonSerializerOptions options)
 87    {
 088        if (value is null)
 89        {
 090            writer.WriteNullValue();
 091            return;
 92        }
 93
 094        writer.WriteStringValue(value.Value.ToUniversalTime().ToString("O", CultureInfo.InvariantCulture));
 095    }
 96}