//----------------------------------------------------------------------- // // Copyright (c) aliasvault. All rights reserved. // Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information. // //----------------------------------------------------------------------- namespace AliasVault.Client.Utilities; using System; using System.Globalization; /// /// Centralized utility for formatting DateTime values consistently across the client application. /// All dates are stored in UTC with the format: "yyyy-MM-dd HH:mm:ss.fff" (23 characters). /// public static class DateTimeFormatter { /// /// The standard date-time format string used throughout the application. /// Format: "yyyy-MM-dd HH:mm:ss.fff" (23 characters with milliseconds). /// public const string StandardFormat = "yyyy-MM-dd HH:mm:ss.fff"; /// /// The standard date format string for BirthDate fields (no time component). /// Format: "yyyy-MM-dd HH:mm:ss" (19 characters, time set to 00:00:00). /// public const string BirthDateFormat = "yyyy-MM-dd HH:mm:ss"; /// /// Formats a DateTime to the standard format string. /// /// The DateTime to format. /// Formatted date-time string in format "yyyy-MM-dd HH:mm:ss.fff". public static string ToStandardFormat(DateTime dateTime) { // Ensure we're working with UTC var utcDateTime = dateTime.Kind == DateTimeKind.Utc ? dateTime : dateTime.ToUniversalTime(); return utcDateTime.ToString(StandardFormat, CultureInfo.InvariantCulture); } /// /// Formats the current UTC time to the standard format string. /// /// Formatted current UTC date-time string. public static string Now() { return ToStandardFormat(DateTime.UtcNow); } /// /// Formats a DateTime to the birth date format (no milliseconds, time set to 00:00:00). /// /// The DateTime to format. /// Formatted date string in format "yyyy-MM-dd 00:00:00". public static string ToBirthDateFormat(DateTime dateTime) { // Ensure we're working with UTC and strip time components var utcDateTime = dateTime.Kind == DateTimeKind.Utc ? dateTime : dateTime.ToUniversalTime(); var dateOnly = new DateTime(utcDateTime.Year, utcDateTime.Month, utcDateTime.Day, 0, 0, 0, DateTimeKind.Utc); return dateOnly.ToString(BirthDateFormat, CultureInfo.InvariantCulture); } /// /// Parses a date string that may be in various formats and returns a DateTime. /// Supports: /// - "yyyy-MM-dd HH:mm:ss.fff" (standard format) /// - "yyyy-MM-dd HH:mm:ss" (without milliseconds) /// - "yyyy-MM-ddTHH:mm:ss.fffZ" (ISO 8601) /// - "yyyy-MM-ddTHH:mm:ssZ" (ISO 8601 without milliseconds) /// Returns DateTime.MinValue if the string cannot be parsed or is null/empty. /// /// The date string to parse. /// Parsed DateTime or DateTime.MinValue if parsing fails. public static DateTime Parse(string? dateString) { if (string.IsNullOrWhiteSpace(dateString)) { return DateTime.MinValue; } // Try standard format first (fastest path) if (DateTime.TryParseExact( dateString, StandardFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var result1)) { return result1; } // Try format without milliseconds if (DateTime.TryParseExact( dateString, BirthDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var result2)) { return result2; } // Try ISO 8601 formats if (DateTime.TryParse( dateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var result3)) { return result3; } // If all parsing fails, return MinValue return DateTime.MinValue; } }