using FluentAssertions; using IBKRTrader.Core.Time; namespace IBKRTrader.Tests.Time; /// /// Sicherheitsnetz für die Betriebszeitzone. Wir betreiben Instanzen in EU und US; die Zeitzone /// darf deshalb nicht mehr an der Zeitzone des Rechners hängen. Diese Tests halten fest, dass /// beide Schreibweisen tragen (Windows-IDs unter Linux, IANA-IDs unter Windows) und dass ein /// unbekannter Wert niemals fatal ist, sondern gemeldet wird. /// [Trait("cat", "unit")] public class AppTimeZoneTests : IDisposable { public void Dispose() => AppTimeZone.Reset(); [Theory] [InlineData("Europe/Berlin")] // IANA – Empfehlung, trägt auf beiden Plattformen [InlineData("W. Europe Standard Time")] // Windows – eine Altkonfiguration muss weiter tragen public void BekannteIds_ErgebenDieselbeZone(string id) { AppTimeZone.Configure(id); // Der Bezeichner unterscheidet sich je Plattform; entscheidend ist der Versatz. AppTimeZone.Current.GetUtcOffset(new DateTime(2026, 1, 15, 12, 0, 0, DateTimeKind.Utc)) .Should().Be(TimeSpan.FromHours(1)); AppTimeZone.Current.GetUtcOffset(new DateTime(2026, 7, 15, 12, 0, 0, DateTimeKind.Utc)) .Should().Be(TimeSpan.FromHours(2)); } [Theory] [InlineData("America/New_York")] [InlineData("Eastern Standard Time")] public void UsZone_TraegtEbenfallsInBeidenSchreibweisen(string id) { AppTimeZone.Configure(id); AppTimeZone.Current.GetUtcOffset(new DateTime(2026, 1, 15, 12, 0, 0, DateTimeKind.Utc)) .Should().Be(TimeSpan.FromHours(-5)); AppTimeZone.Current.GetUtcOffset(new DateTime(2026, 7, 15, 12, 0, 0, DateTimeKind.Utc)) .Should().Be(TimeSpan.FromHours(-4)); } [Fact] public void UnbekannteId_WeichtAufDieSystemzoneAus_UndWarnt() { string? warning = null; AppTimeZone.Configure("Gibt/EsNicht", w => warning = w); AppTimeZone.Current.Id.Should().Be(TimeZoneInfo.Local.Id); warning.Should().NotBeNull().And.Contain("Gibt/EsNicht"); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void LeereAngabe_BedeutetSystemzone_UndWarnt(string? id) { string? warning = null; AppTimeZone.Configure(id, w => warning = w); AppTimeZone.Current.Id.Should().Be(TimeZoneInfo.Local.Id); warning.Should().NotBeNull("eine unbestimmte Betriebszeitzone ist ein Betriebsrisiko"); } [Fact] public void ToDisplay_RechnetUtcInDieKonfigurierteZone() { AppTimeZone.Configure("Europe/Berlin"); // 12:00 UTC im Januar = 13:00 Berliner Zeit (MEZ). AppTimeZone.ToDisplay(new DateTime(2026, 1, 15, 12, 0, 0, DateTimeKind.Utc)).Hour.Should().Be(13); } [Fact] public void ToDisplay_TrenntEuUndUs() { var utc = new DateTime(2026, 7, 15, 16, 0, 0, DateTimeKind.Utc); AppTimeZone.Configure("Europe/Berlin"); AppTimeZone.ToDisplay(utc).Hour.Should().Be(18); // UTC+2 AppTimeZone.Configure("America/New_York"); AppTimeZone.ToDisplay(utc).Hour.Should().Be(12); // UTC-4 } }