| File: Dcp\Model\KubernetesMicroTimeJsonConverter.cs | Web Access |
| Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; namespace Aspire.Hosting.Dcp.Model; internal sealed class KubernetesMicroTimeJsonConverter : JsonConverter<DateTime?> { private const string UtcFormat = "yyyy-MM-dd'T'HH:mm:ss.ffffff'Z'"; private const string OffsetFormat = "yyyy-MM-dd'T'HH:mm:ss.ffffffzzz"; public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType is JsonTokenType.Null) { return null; } if (reader.TokenType is not JsonTokenType.String) { throw new JsonException($"Expected a string token for Kubernetes MicroTime but found {reader.TokenType}."); } var value = reader.GetString(); if (string.IsNullOrEmpty(value)) { throw new JsonException("Expected a non-empty Kubernetes MicroTime value."); } return value.EndsWith('Z') ? DateTime.ParseExact(value, UtcFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) : DateTimeOffset.ParseExact(value, OffsetFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal).UtcDateTime; } public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) { if (value is null) { writer.WriteNullValue(); return; } // DCP models these fields as Kubernetes metav1.MicroTime, whose JSON shape is fixed-width: // "2026-07-15T18:46:06.123000Z" // See https://github.com/kubernetes/apimachinery/blob/v0.36.0/pkg/apis/meta/v1/micro_time.go. // System.Text.Json trims fractional seconds for DateTime by default, which DCP rejects when // the value is submitted to the API server. var timestamp = value.Value.Kind switch { DateTimeKind.Utc => value.Value, DateTimeKind.Local => value.Value.ToUniversalTime(), _ => DateTime.SpecifyKind(value.Value, DateTimeKind.Utc) }; writer.WriteStringValue(timestamp.ToString(UtcFormat, CultureInfo.InvariantCulture)); } }