| | | 1 | | namespace ArturRios.Heimdall.Shared.Time; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// Reads an instant a caller sent as the UTC instant this API's contract says it is |
| | | 5 | | /// (UC-48's <c>From</c>/<c>To</c>, UC-53's <c>ExpiresAt</c>). |
| | | 6 | | /// </summary> |
| | | 7 | | /// <remarks> |
| | | 8 | | /// ASP.NET Core binds <c>2026-10-14T00:00:00Z</c> as UTC but <c>2026-10-14T00:00:00</c>, with no |
| | | 9 | | /// offset, as <see cref="DateTimeKind.Unspecified" />, and Npgsql refuses an unspecified |
| | | 10 | | /// <see cref="DateTime" /> for a <c>timestamp with time zone</c> parameter. Without this an |
| | | 11 | | /// offset-less filter — what an HTML <c>datetime-local</c> input sends — would answer 500. |
| | | 12 | | /// </remarks> |
| | | 13 | | public static class UtcInstant |
| | | 14 | | { |
| | | 15 | | /// <summary> |
| | | 16 | | /// <paramref name="value" /> as UTC: unchanged when it already is, converted when it is local, |
| | | 17 | | /// and taken as UTC when it carries no kind at all. |
| | | 18 | | /// </summary> |
| | 29 | 19 | | public static DateTime Of(DateTime value) => value.Kind switch |
| | 29 | 20 | | { |
| | 17 | 21 | | DateTimeKind.Utc => value, |
| | 1 | 22 | | DateTimeKind.Local => value.ToUniversalTime(), |
| | 11 | 23 | | _ => DateTime.SpecifyKind(value, DateTimeKind.Utc) |
| | 29 | 24 | | }; |
| | | 25 | | } |