MilliSim/backend/MilliSim.Api/Common/Models/BeijingTimeConverter.cs

146 lines
5.0 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MilliSim.Common.Models;
/// <summary>
/// 北京时间UTC+8JSON转换器
/// 将 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));
}
}