using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace GB5Shared.DateConverter
{
///
/// GB5 standard DateOnly converter.
/// READ : "yyyy-MM-dd" ISO date string only
/// WRITE: "yyyy-MM-dd"
///
/// Epoch /Date(N)/ format is NO LONGER accepted — removed by design.
///
public sealed class DateOnlyJsonConverter : JsonConverter
{
public override DateOnly Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
return DateOnly.MinValue;
if (reader.TokenType == JsonTokenType.String)
{
var raw = reader.GetString();
if (string.IsNullOrWhiteSpace(raw))
return DateOnly.MinValue;
if (DateOnly.TryParseExact(raw, "yyyy-MM-dd",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None, out var date))
return date;
// Accept full ISO datetime string — extract date portion only
if (DateTime.TryParse(raw, System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.RoundtripKind, out var dt))
return DateOnly.FromDateTime(dt);
throw new JsonException(
$"Invalid date value '{raw}'. Expected ISO format 'yyyy-MM-dd'.");
}
throw new JsonException(
$"Unexpected token {reader.TokenType} for DateOnly; expected a string.");
}
public override void Write(
Utf8JsonWriter writer,
DateOnly value,
JsonSerializerOptions options)
{
if (value == DateOnly.MinValue)
{
writer.WriteNullValue();
return;
}
writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
}
}
public sealed class NullableDateOnlyJsonConverter : JsonConverter
{
private static readonly DateOnlyJsonConverter _inner = new();
public override DateOnly? Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
return null;
var val = _inner.Read(ref reader, typeof(DateOnly), options);
return val == DateOnly.MinValue ? null : val;
}
public override void Write(
Utf8JsonWriter writer,
DateOnly? value,
JsonSerializerOptions options)
{
if (!value.HasValue)
{
writer.WriteNullValue();
return;
}
_inner.Write(writer, value.Value, options);
}
}
}