From 4e70b0f847204d5040b5550977e7d15d17c75d06 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Sat, 18 Apr 2026 09:43:35 -0300 Subject: [PATCH] feat(udt-011): TimeProviderArgentinaExtensions.GetArgentinaToday cross-platform --- .../Common/TimeProviderArgentinaExtensions.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/api/SIGCM2.Application/Common/TimeProviderArgentinaExtensions.cs diff --git a/src/api/SIGCM2.Application/Common/TimeProviderArgentinaExtensions.cs b/src/api/SIGCM2.Application/Common/TimeProviderArgentinaExtensions.cs new file mode 100644 index 0000000..efed334 --- /dev/null +++ b/src/api/SIGCM2.Application/Common/TimeProviderArgentinaExtensions.cs @@ -0,0 +1,45 @@ +namespace SIGCM2.Application.Common; + +/// +/// Extension methods for that expose Argentina-localized +/// date helpers. Handles the UTC-3 offset cross-platform (IANA / Windows TZ IDs). +/// +/// UDT-011: Cat2 fields (VigenciaDesde, etc.) must use civil Argentine date, never +/// raw UTC, to avoid date-creep during the 22:00–23:59 window. +/// +public static class TimeProviderArgentinaExtensions +{ + // IANA TZ id — Linux / macOS / .NET 8+ on Windows with ICU + public const string ArgentinaTimeZoneId = "America/Argentina/Buenos_Aires"; + + // Windows built-in TZ id — fallback for environments without ICU + public const string ArgentinaTimeZoneIdWindows = "Argentina Standard Time"; + + private static readonly TimeZoneInfo ArgentinaTz = LoadArgentinaTz(); + + /// + /// Returns today's civil date in Argentina timezone, computed from the + /// UTC clock. + /// Safe in tests via FakeTimeProvider; safe in production via + /// TimeProvider.System. + /// + public static DateOnly GetArgentinaToday(this TimeProvider timeProvider) + { + var utcNow = timeProvider.GetUtcNow(); + var argentinaNow = TimeZoneInfo.ConvertTime(utcNow, ArgentinaTz); + return DateOnly.FromDateTime(argentinaNow.DateTime); + } + + private static TimeZoneInfo LoadArgentinaTz() + { + try + { + return TimeZoneInfo.FindSystemTimeZoneById(ArgentinaTimeZoneId); + } + catch (TimeZoneNotFoundException) + { + // Windows without ICU: fall back to built-in Windows TZ name + return TimeZoneInfo.FindSystemTimeZoneById(ArgentinaTimeZoneIdWindows); + } + } +}