146 lines
5.0 KiB
C#
146 lines
5.0 KiB
C#
using System.Globalization;
|
||
using System.Text.Json;
|
||
using System.Text.Json.Serialization;
|
||
|
||
namespace MilliSim.Common.Models;
|
||
|
||
/// <summary>
|
||
/// 北京时间(UTC+8)JSON转换器
|
||
/// 将 DateTime 序列化为北京时间格式 "yyyy-MM-dd HH:mm:ss"
|
||
/// </summary>
|
||
public class BeijingTimeConverter : JsonConverter<DateTime>
|
||
{
|
||
/// <summary>
|
||
/// 北京时区信息(UTC+8)
|
||
/// </summary>
|
||
private static readonly TimeZoneInfo BeijingTimeZone = TimeZoneInfo.FindSystemTimeZoneById(
|
||
OperatingSystem.IsWindows() ? "China Standard Time" : "Asia/Shanghai");
|
||
|
||
/// <summary>
|
||
/// 北京时间格式
|
||
/// </summary>
|
||
private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
|
||
|
||
/// <summary>
|
||
/// 读取JSON并转换为DateTime
|
||
/// </summary>
|
||
/// <param name="reader">JSON读取器</param>
|
||
/// <param name="typeToConvert">要转换的类型</param>
|
||
/// <param name="options">序列化选项</param>
|
||
/// <returns>DateTime对象</returns>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将DateTime写入JSON(转换为北京时间格式)
|
||
/// </summary>
|
||
/// <param name="writer">JSON写入器</param>
|
||
/// <param name="value">DateTime值</param>
|
||
/// <param name="options">序列化选项</param>
|
||
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));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 可空DateTime的北京时间JSON转换器
|
||
/// </summary>
|
||
public class NullableBeijingTimeConverter : JsonConverter<DateTime?>
|
||
{
|
||
/// <summary>
|
||
/// 北京时区信息(UTC+8)
|
||
/// </summary>
|
||
private static readonly TimeZoneInfo BeijingTimeZone = TimeZoneInfo.FindSystemTimeZoneById(
|
||
OperatingSystem.IsWindows() ? "China Standard Time" : "Asia/Shanghai");
|
||
|
||
/// <summary>
|
||
/// 北京时间格式
|
||
/// </summary>
|
||
private const string DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
|
||
|
||
/// <summary>
|
||
/// 读取JSON并转换为可空DateTime
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将可空DateTime写入JSON(转换为北京时间格式)
|
||
/// </summary>
|
||
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));
|
||
}
|
||
}
|