//-----------------------------------------------------------------------
//
// 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;
}
}