忘忧的小站

  • 首页
  • 文章归档
  • 日志
  • 关于页面

  • 搜索
分布式索引 索引 全文搜索 Lucene.Net GPS 音视频 过滤 AOP 时区 升级 ABP.Zero 数据备份 linux 阿里云盘 aliyunpan 面试题 Signalr S 汉字 css html 前端 拼音键盘 在线键盘 uniapp .Net Core XMLRPC Serilog LOKI Nlog 分布式日志 加密 总结 人生 Asp.Net Core Swagger Web Element-plus Quasar 匹配 JavaScript 正则 .Net 后台 架构师 Redis EF CORE MySQL 自考 英语 集群 Jenkins CI/DI 内网穿透 代理 ABP 学习 后端 软考

.Net7 针对Utc时区转换问题中间件

发表于 2023-10-31 | 分类于 .Net Core | 0 | 阅读次数 1500

为什么要存储UTC时间

存储UTC(协调世界时)时间是为了在跨时区和时间转换的情况下保持时间的一致性和准确性。以下是一些原因:

  1. 时区独立性:UTC时间是不受时区影响的,它是全球标准时间。通过存储UTC时间,可以避免在不同时区之间进行转换和处理,确保时间的一致性,无论用户位于何处。

  2. 跨时区应用:对于涉及跨时区操作的应用程序,使用UTC时间可以简化时间计算和比较。如果存储本地时间,可能会面临时区转换和夏令时变更等问题,导致时间计算不准确。

  3. 数据一致性:当多个系统或数据库需要共享时间信息时,使用UTC时间可以确保数据的一致性。不同系统和数据库可以根据需要将UTC时间转换为本地时间进行显示,以满足用户的需求,而不会引起数据不一致的问题。

  4. 日志和审计:在日志记录和审计方面,使用UTC时间可以提供统一的时间戳,使得跨系统和跨地点的日志可以进行准确的时间排序和比较。

  5. 时间计算的准确性:在进行时间计算、持续时间计算或时间间隔比较时,使用UTC时间可以避免由于夏令时等因素引起的时间偏移和不一致性,确保计算的准确性。

总之,存储UTC时间可以提供时间的一致性、跨时区操作的便利性以及数据的一致性,尤其适用于涉及多个时区的应用程序和系统。当需要进行时间转换或比较时,可以将UTC时间转换为本地时间进行显示,以满足最终用户的需求。

代码中实现

var dateTime = Datetime.UtcNow;

如果这样实现的话那么接口请求的时间和请求返回的时间都需要手动处理,这样不不够优雅的

如何处理

安装Newtonsoft.Json库
增加DateTimeFilter.cs

public class DateTimeFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        var parameters = context.ActionArguments;
        foreach (var parameter in parameters)
        {
           
            if (parameter.Value is DateTime dateTime)
            {
                dateTime = dateTime.ToUniversalTime();
                context.ActionArguments[parameter.Key] = dateTime;
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
    }
}

增加DateTimeJsonConverter.cs

public class DateTimeJsonConverter : DateTimeConverterBase
{
    
    public DateTimeJsonConverter()
    {
    }
  
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {

        
        
        // 用户配置的时区 ,建议使用Redis 或者内存缓存
        var setting = "";
        if (setting.IsNullOrEmpty())
        {
            DateTime dateTime = (DateTime)value;
            writer.WriteValue(dateTime.ToLocalTime());
        }
        else
        {
            TimeZoneInfo targetTimeZone = TimeZoneInfo.FindSystemTimeZoneById(setting);
            DateTime targetTime = TimeZoneInfo.ConvertTimeFromUtc((DateTime) value, targetTimeZone);
            writer.WriteValue(targetTime);
        }

    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        DateTime dateTime = (DateTime)reader.Value;
        return dateTime.ToUniversalTime();
    }
}

在Program.cs 中注册

builder.Services.AddControllers(o =>
{
        o.Filters.Add(typeof(DateTimeFilter));
}).AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();
    options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
    options.SerializerSettings.Converters.Add(new StringEnumConverter());
    options.SerializerSettings.Converters.Add(new DateTimeJsonConverter());

})

DateTimeFilter 是针对以下接口入参形式

        [HttpGet("utc")]
        public IActionResult Utc(DateTime utc)
        {
            return Ok(utc);
        }

DateTimeJsonConverter 是捕获不到接口的参数,只能捕获入参对象,和返回对象

    public class MyClass
        {
            public DateTime Utc { get; set; }
            
            public MyClass1 MyClassx { get; set; }
            public class MyClass1
            {
                public DateTime Utc1 { get; set; }
            }
        }
        [HttpGet("utc")]
        public IActionResult Utc(MyClass utc)
        {
            return Ok(utc);
        }
        
        //获取所有时区
         [HttpGet("TimeZone")]
        public IActionResult List()
        {
            var list = TimeZoneInfo.GetSystemTimeZones();
            return Ok(list.Select(x =>
            {
                return new
                {
                    Id = x.Id,
                    DisplayName = x.DisplayName
                };
            }).ToList());
        }

这样就实现对传入参数和返回参数 DateTime 类型转UTC时间再转回当前时区的实现
在 Controller和 Services及Repository就不用再处理Datetime 类型时区转换的代码了, 直接可以使用

  • 本文作者: 忘忧
  • 本文链接: /archives/183
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# .Net # 时区 # AOP # 过滤
Abp.Zero框架升级
JavaScript授权Gps,音频,视频踩坑
  • 文章目录
  • 站点概览
忘忧

忘忧

君子藏器于身,待时而动,何不利之有

44 日志
6 分类
60 标签
RSS
Github E-mail StackOverflow
Creative Commons
0%
© 2025 忘忧
由 Halo 强力驱动