Terminal nach Avalonia + konfigurierbare Zeitzone (P2-Kern)
Alle vier Core-Fenster sind damit portiert. TERMINAL: - Live-Ausgabe als virtualisiertes ItemsControl ueber eine begrenzte Zeilenliste statt RichTextBox. Damit entfaellt das Auto-Clear der WinForms-Fassung, das bei Erreichen der Zeichengrenze den GESAMTEN Verlauf verwarf - jetzt werden nur die aeltesten Zeilen verdraengt (Ringpuffer, 5000 Zeilen), der juengste Verlauf bleibt immer sichtbar. Die Zeilenzahl steht in der Statuszeile. - Log-Viewer unveraendert im Funktionsumfang: JSONL-Tagesdateien, Filter nach Datum, Level, CID und Volltext, Doppelklick uebernimmt die CID (Signal-Kette verfolgen). ZEITZONE (Befund aus der Linux-Analyse, hier faellig geworden): Die Terminal-Ansicht rechnete hart gegen die WINDOWS-ID 'W. Europe Standard Time'. Auf Linux traegt die nur ueber die ICU-Zuordnung und faellt ganz aus, wenn ICU fehlt oder InvariantGlobalization gesetzt ist - das Fenster haette beim Oeffnen geworfen. Neu: PolyTraderSharp.Services.AppTimeZone + ServerSettings.ApplicationTimeZoneId (Default 'Europe/Berlin', IANA-Schreibweise). Aufloesung versucht die ID direkt, dann die jeweils andere Schreibweise (IANA<->Windows), zuletzt die Systemzeitzone - ein unbekannter Wert ist damit nie fatal, sondern erzeugt nur eine Warnung. Beide Programm-Einstiege setzen sie einmalig beim Start; laut Vorgabe wird sie bei der Installation festgelegt und nicht im laufenden Betrieb gewechselt (Aenderung verschiebt Logdatei-Tagesgrenzen). 8 neue Tests (AppTimeZoneTests) halten fest: IANA- UND Windows-ID liefern denselben UTC-Versatz (Winter +1, Sommer +2), unbekannte IDs fallen mit Warnung auf die Systemzeitzone zurueck, leere Angabe = Systemzeitzone, UTC wird korrekt umgerechnet. Verifiziert: Solution baut, 450 Tests gruen, --smoke-ui gruen (6 Fenster + Editor-Pruefung, Zeitzone loest als Europe/Berlin auf), App laeuft real, Linux-Publish laeuft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
|
||||
namespace PolyTraderSharp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Anzeige-Zeitzone der Anwendung. Wird beim Start EINMAL aus den Server-Settings gesetzt
|
||||
/// (<c>ApplicationTimeZoneId</c>) und danach überall zum Umrechnen von UTC-Zeitstempeln in die
|
||||
/// dargestellte Ortszeit verwendet.
|
||||
///
|
||||
/// <para><b>Warum das nötig war:</b> Die Terminal-Ansicht rechnete bisher hart gegen
|
||||
/// <c>"W. Europe Standard Time"</c> – eine <i>Windows</i>-Zeitzonen-ID. Auf Linux funktioniert die
|
||||
/// nur über die ICU-Zuordnung und fällt komplett aus, wenn ICU fehlt oder
|
||||
/// <c>InvariantGlobalization</c> gesetzt ist. Dann hätte das Fenster beim Öffnen geworfen.</para>
|
||||
///
|
||||
/// <para><b>Auflösung:</b> Zuerst die konfigurierte ID direkt, dann über die Umrechnung zwischen
|
||||
/// IANA- und Windows-Schreibweise (damit dieselbe Konfiguration auf beiden Plattformen trägt),
|
||||
/// zuletzt die Zeitzone des Systems. Ein Fehlschlag ist damit nie fatal – er wird nur gemeldet.</para>
|
||||
///
|
||||
/// <para>Die Zeitzone wird bewusst einmalig bei der Installation festgelegt und nicht im
|
||||
/// laufenden Betrieb gewechselt: eine Änderung verschiebt Logdatei-Tagesgrenzen und
|
||||
/// Auswertungszeiträume. Änderungen greifen deshalb erst nach einem Neustart.</para>
|
||||
/// </summary>
|
||||
public static class AppTimeZone
|
||||
{
|
||||
/// <summary>Empfehlung für neue Installationen – IANA-Schreibweise, funktioniert auf beiden Plattformen.</summary>
|
||||
public const string DefaultId = "Europe/Berlin";
|
||||
|
||||
/// <summary>Aktuell gültige Anzeige-Zeitzone. Vor <see cref="Configure"/> die des Systems.</summary>
|
||||
public static TimeZoneInfo Current { get; private set; } = TimeZoneInfo.Local;
|
||||
|
||||
/// <summary>Die tatsächlich verwendete ID (kann von der gewünschten abweichen, wenn ausgewichen wurde).</summary>
|
||||
public static string CurrentId => Current.Id;
|
||||
|
||||
/// <summary>
|
||||
/// Setzt die Anzeige-Zeitzone. Leere Angabe = Systemzeitzone. Meldet über
|
||||
/// <paramref name="warn"/>, wenn auf etwas anderes als das Gewünschte ausgewichen wurde.
|
||||
/// </summary>
|
||||
public static void Configure(string? timeZoneId, Action<string>? warn = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(timeZoneId))
|
||||
{
|
||||
Current = TimeZoneInfo.Local;
|
||||
return;
|
||||
}
|
||||
|
||||
string id = timeZoneId.Trim();
|
||||
if (TryFind(id, out var tz)) { Current = tz!; return; }
|
||||
|
||||
// Andere Schreibweise versuchen: eine unter Windows gepflegte Konfiguration soll auch
|
||||
// auf Linux tragen und umgekehrt.
|
||||
if (TimeZoneInfo.TryConvertIanaIdToWindowsId(id, out string? windowsId)
|
||||
&& TryFind(windowsId!, out tz))
|
||||
{
|
||||
Current = tz!;
|
||||
warn?.Invoke($"Zeitzone „{id}\" wurde als „{tz!.Id}\" aufgelöst.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TimeZoneInfo.TryConvertWindowsIdToIanaId(id, out string? ianaId)
|
||||
&& TryFind(ianaId!, out tz))
|
||||
{
|
||||
Current = tz!;
|
||||
warn?.Invoke($"Zeitzone „{id}\" wurde als „{tz!.Id}\" aufgelöst.");
|
||||
return;
|
||||
}
|
||||
|
||||
Current = TimeZoneInfo.Local;
|
||||
warn?.Invoke($"⚠️ Zeitzone „{id}\" ist auf diesem System unbekannt – es wird die Systemzeitzone " +
|
||||
$"„{TimeZoneInfo.Local.Id}\" verwendet. Empfohlen ist die IANA-Schreibweise, z.B. „{DefaultId}\".");
|
||||
}
|
||||
|
||||
/// <summary>Rechnet einen Zeitstempel in die Anzeige-Zeitzone um (UTC-Kennzeichnung wird beachtet).</summary>
|
||||
public static DateTime ToDisplay(DateTime value) =>
|
||||
value.Kind == DateTimeKind.Utc
|
||||
? TimeZoneInfo.ConvertTimeFromUtc(value, Current)
|
||||
: TimeZoneInfo.ConvertTime(value, Current);
|
||||
|
||||
private static bool TryFind(string id, out TimeZoneInfo? tz)
|
||||
{
|
||||
try { tz = TimeZoneInfo.FindSystemTimeZoneById(id); return true; }
|
||||
catch (TimeZoneNotFoundException) { tz = null; return false; }
|
||||
catch (InvalidTimeZoneException) { tz = null; return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user