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