using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; namespace MilliSim.Common.Models; /// /// 北京时间(UTC+8)JSON转换器 /// 将 DateTime 序列化为北京时间格式 "yyyy-MM-dd HH:mm:ss" /// public class BeijingTimeConverter : JsonConverter { /// /// 北京时区信息(UTC+8) /// private static readonly TimeZoneInfo BeijingTimeZone = TimeZoneInfo.FindSystemTimeZoneById( OperatingSystem.IsWindows() ? "China Standard Time" : "Asia/Shanghai"); /// /// 北京时间格式 /// private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; /// /// 读取JSON并转换为DateTime /// /// JSON读取器 /// 要转换的类型 /// 序列化选项 /// DateTime对象 public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 读取字符串值 var dateString = reader.GetString(); if (string.IsNullOrEmpty(dateString)) return DateTime.MinValue; // 尝试解析为北京时间 if (DateTime.TryParseExact(dateString, DateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) { // 将北京时间转换为本地时间(按Kind处理) return DateTime.SpecifyKind(result, DateTimeKind.Local); } // 兜底:使用默认解析 return DateTime.Parse(dateString, CultureInfo.InvariantCulture); } /// /// 将DateTime写入JSON(转换为北京时间格式) /// /// JSON写入器 /// DateTime值 /// 序列化选项 public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { // 将DateTime转换为北京时间 DateTime beijingTime; if (value.Kind == DateTimeKind.Utc) { // UTC时间转换为北京时间 beijingTime = TimeZoneInfo.ConvertTimeFromUtc(value, BeijingTimeZone); } else if (value.Kind == DateTimeKind.Unspecified) { // 未指定类型的时间,假定为本地时间并转换为北京时间 beijingTime = TimeZoneInfo.ConvertTime(value, BeijingTimeZone); } else { // 已经是本地时间,转换为北京时间 beijingTime = TimeZoneInfo.ConvertTime(value, BeijingTimeZone); } // 格式化为 "yyyy-MM-dd HH:mm:ss" 并写入 writer.WriteStringValue(beijingTime.ToString(DateTimeFormat, CultureInfo.InvariantCulture)); } } /// /// 可空DateTime的北京时间JSON转换器 /// public class NullableBeijingTimeConverter : JsonConverter { /// /// 北京时区信息(UTC+8) /// private static readonly TimeZoneInfo BeijingTimeZone = TimeZoneInfo.FindSystemTimeZoneById( OperatingSystem.IsWindows() ? "China Standard Time" : "Asia/Shanghai"); /// /// 北京时间格式 /// private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; /// /// 读取JSON并转换为可空DateTime /// public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) return null; var dateString = reader.GetString(); if (string.IsNullOrEmpty(dateString)) return null; if (DateTime.TryParseExact(dateString, DateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)) { return DateTime.SpecifyKind(result, DateTimeKind.Local); } return DateTime.Parse(dateString, CultureInfo.InvariantCulture); } /// /// 将可空DateTime写入JSON(转换为北京时间格式) /// public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); return; } // 将DateTime转换为北京时间 DateTime beijingTime; var dt = value.Value; if (dt.Kind == DateTimeKind.Utc) { beijingTime = TimeZoneInfo.ConvertTimeFromUtc(dt, BeijingTimeZone); } else if (dt.Kind == DateTimeKind.Unspecified) { beijingTime = TimeZoneInfo.ConvertTime(dt, BeijingTimeZone); } else { beijingTime = TimeZoneInfo.ConvertTime(dt, BeijingTimeZone); } writer.WriteStringValue(beijingTime.ToString(DateTimeFormat, CultureInfo.InvariantCulture)); } }