using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace GB5Shared.DateConverter
{
///
/// GB5 standard DateTime converter.
/// READ : ISO 8601 — "yyyy-MM-ddTHH:mm:ssZ" / "yyyy-MM-dd"
/// Legacy — "/Date(milliseconds)/" or "/Date(milliseconds+offset)/"
/// WRITE: "yyyy-MM-ddTHH:mm:ss.fffZ" (UTC ISO 8601)
///
public class MicrosoftDateConverter : JsonConverter
{
public override DateTime Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
return DateTime.MinValue;
if (reader.TokenType == JsonTokenType.String)
{
var value = reader.GetString();
if (string.IsNullOrWhiteSpace(value))
return DateTime.MinValue;
// Legacy Microsoft /Date(milliseconds)/ or /Date(milliseconds+offset)/ format
if (value.StartsWith("/Date(", StringComparison.Ordinal) && value.EndsWith(")/", StringComparison.Ordinal))
{
var inner = value.Substring(6, value.Length - 8);
var signIdx = inner.IndexOfAny(new[] { '+', '-' });
var msStr = signIdx > 0 ? inner.Substring(0, signIdx) : inner;
if (long.TryParse(msStr, out long ms))
return DateTimeOffset.FromUnixTimeMilliseconds(ms).UtcDateTime;
return DateTime.MinValue;
}
if (DateTime.TryParse(value, null,
System.Globalization.DateTimeStyles.RoundtripKind, out DateTime parsed))
return parsed.Kind == DateTimeKind.Unspecified
? DateTime.SpecifyKind(parsed, DateTimeKind.Utc)
: parsed.ToUniversalTime();
return DateTime.MinValue;
}
return DateTime.MinValue;
}
public override void Write(
Utf8JsonWriter writer,
DateTime value,
JsonSerializerOptions options)
{
if (value == DateTime.MinValue || value == default)
{
writer.WriteNullValue();
return;
}
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
}
}
}