245 lines
7.3 KiB
C#
245 lines
7.3 KiB
C#
using IRaCIS.Core.Domain.Share;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Converters;
|
||
using System;
|
||
using System.Globalization;
|
||
|
||
namespace IRaCIS.Core.API
|
||
{
|
||
/// <summary>
|
||
/// 序列化,反序列化的时候,处理时间 时区转换
|
||
/// </summary>
|
||
public class JSONTimeZoneConverter(IHttpContextAccessor _httpContextAccessor) : DateTimeConverterBase
|
||
{
|
||
|
||
private TimeZoneInfo _clientTimeZone;
|
||
|
||
private string _dateFormat;
|
||
|
||
|
||
|
||
public override bool CanConvert(Type objectType)
|
||
{
|
||
#region 设置语言格式化方式,放在构造函数里面做不到动态切换
|
||
|
||
|
||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||
|
||
if (!isEn_US)
|
||
{
|
||
// Chinese date format
|
||
_dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||
}
|
||
else
|
||
{
|
||
// Default or English date format
|
||
//_dateFormat = "MM/dd/yyyy HH:mm:ss";
|
||
|
||
_dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 获取当前请求的客户端时区
|
||
|
||
//var timeZoneId = "Etc/UTC";
|
||
var timeZoneId = "Asia/Shanghai";
|
||
var timeZoneIdHeader = _httpContextAccessor?.HttpContext?.Request?.Headers["TimeZoneId"];
|
||
|
||
if (timeZoneIdHeader is not null && !string.IsNullOrEmpty(timeZoneIdHeader.Value))
|
||
{
|
||
timeZoneId = timeZoneIdHeader.Value;
|
||
}
|
||
|
||
_clientTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
|
||
|
||
#endregion
|
||
|
||
|
||
// 仅支持 DateTime 类型的转换
|
||
return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
|
||
|
||
}
|
||
|
||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||
{
|
||
if (reader.Value == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
DateTime dateTime;
|
||
|
||
// 2. 检查目标类型是否可空
|
||
bool isNullable = objectType == typeof(DateTime?);
|
||
|
||
var canConvert = DateTime.TryParse(reader.Value?.ToString(), out dateTime);
|
||
|
||
|
||
if (isNullable == false && canConvert == false)
|
||
{
|
||
|
||
throw new JsonSerializationException($"Could not convert string to DateTime: {reader.Value} Path {reader.Path}");
|
||
}
|
||
else
|
||
{
|
||
if (canConvert == false)
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
////如果前端传递带时区的,那么转换会报错,需要DateTimeKind.Unspecified
|
||
//dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
|
||
|
||
// 将客户端时间转换为服务器时区的时间
|
||
var serverZoneTime = TimeZoneInfo.ConvertTime(dateTime, _clientTimeZone, TimeZoneInfo.Local);
|
||
|
||
return serverZoneTime;
|
||
|
||
|
||
|
||
}
|
||
|
||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||
{
|
||
DateTime? nullableDateTime = value as DateTime?;
|
||
|
||
if (nullableDateTime != null && nullableDateTime.HasValue)
|
||
{
|
||
//第一个参数默认使用系统本地时区 也就是应用服务器的时区
|
||
DateTime clientZoneTime = TimeZoneInfo.ConvertTime(nullableDateTime.Value, _clientTimeZone);
|
||
|
||
|
||
//// 最简单的方式:创建 DateTimeOffset
|
||
//DateTimeOffset dateTimeOffset = new DateTimeOffset(clientZoneTime, _clientTimeZone.GetUtcOffset(clientZoneTime));
|
||
//writer.WriteValue(dateTimeOffset.ToString("yyyy-MM-dd HH:mm:sszzz"));
|
||
|
||
writer.WriteValue(clientZoneTime.ToString(_dateFormat));
|
||
}
|
||
else
|
||
{
|
||
writer.WriteNull();
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
public class DateOnlyUniversalJsonConverter : JsonConverter
|
||
{
|
||
private readonly string _format;
|
||
|
||
public DateOnlyUniversalJsonConverter(string format = "yyyy-MM-dd")
|
||
{
|
||
_format = format;
|
||
}
|
||
|
||
public override bool CanConvert(Type objectType)
|
||
{
|
||
return objectType == typeof(DateOnly) || objectType == typeof(DateOnly?);
|
||
}
|
||
|
||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
||
{
|
||
if (value == null)
|
||
{
|
||
writer.WriteValue(""); // null -> 空字符串
|
||
return;
|
||
}
|
||
|
||
var date = (DateOnly)value;
|
||
if (date == default)
|
||
{
|
||
writer.WriteValue(""); // default(DateOnly) -> 空字符串
|
||
}
|
||
else
|
||
{
|
||
writer.WriteValue(date.ToString(_format));
|
||
}
|
||
}
|
||
|
||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
||
{
|
||
var str = reader.TokenType == JsonToken.Null ? null : reader.Value?.ToString();
|
||
|
||
if (string.IsNullOrWhiteSpace(str) || !DateOnly.TryParse(str, out var date))
|
||
{
|
||
return objectType == typeof(DateOnly?) ? null : default(DateOnly);
|
||
}
|
||
|
||
return date;
|
||
}
|
||
}
|
||
|
||
#region 废弃
|
||
|
||
public class MyDateTimeConverter : JsonConverter<DateTime>
|
||
{
|
||
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||
{
|
||
return reader.ReadAsDateTime().Value;
|
||
}
|
||
|
||
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
|
||
{
|
||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||
|
||
string dateFormat;
|
||
if (!isEn_US)
|
||
{
|
||
// Chinese date format
|
||
dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||
}
|
||
else
|
||
{
|
||
// Default or English date format
|
||
dateFormat = "MM/dd/yyyy HH:mm:ss";
|
||
}
|
||
|
||
writer.WriteValue(value.ToString(dateFormat));
|
||
|
||
}
|
||
}
|
||
|
||
public class MyNullableDateTimeConverter : JsonConverter<DateTime?>
|
||
{
|
||
public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||
{
|
||
var val = reader.ReadAsDateTime();
|
||
return val;
|
||
}
|
||
|
||
public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer)
|
||
{
|
||
var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US;
|
||
|
||
string dateFormat;
|
||
if (!isEn_US)
|
||
{
|
||
// Chinese date format
|
||
dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||
}
|
||
else
|
||
{
|
||
// Default or English date format
|
||
dateFormat = "MM/dd/yyyy HH:mm:ss";
|
||
}
|
||
|
||
if (value.HasValue)
|
||
{
|
||
writer.WriteValue(value.Value.ToString(dateFormat));
|
||
|
||
}
|
||
else
|
||
{
|
||
writer.WriteValue(default(DateTime?));
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|