NET发布云服务器的时区问题
2022/4/25 23:12:42
本文主要是介绍NET发布云服务器的时区问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一劳永逸,解决.NET发布云服务器的时区问题
国内大多数开发者使用的电脑,都是使用的北京时间,日常开发的过程中其实并没有什么不便;不过,等遇到了阿里云等云服务器,系统默认使用的时间大多为UTC时间,这个时候,时区和时间的问题,就是不容忽视的大问题。
概念
首先明确一点,对于一个时刻,不管你用UTC时间还是UTC+8的时间来表示,本质上是一个时刻,就是一样的。我们处理日期和时间的目标,也是为了保证这个时刻不会因为时区的不同出现对不上的情况。
DateTime与DateTimeOffset
.NET中表示时刻的数据类型有这两个(新出的Date和Time不作讨论),关于这两个数据类型,已经有同学写的很清楚了,阿里云很多服务器使用的时间为UTC时间,这个时候,如果使用DateTime,是很难说清楚时区(Kind只有UTC、Local还有未指定,不支持特定的某个时区),因此我们应当优先使用DateTimeOffset。
TimeZoneInfo
用于跨时区的情况下,时区的信息是很重要的,.NET中使用TimeZoneInfo这个类表示时区的信息。该类提供了一些静态方法,可以用于查找时区和创建时区等等。最早我是倾向于使用这些方法找到东八区的信息的,但是我发现诸如ConvertTimeBySystemTimeZoneId
和FindSystemTimeZoneById
的方法,都依赖于系统中的定义,不同的系统可能还不一样,自己定义是比较保险的,于是,我使用了CreateCustomTimeZone
来新建一个时区。
Unix时间戳是比较于1970年的UTC标准时间,因此在处理的过程中,DateTime的时间表示应当将它转换为UTC时间,以下的代码,是使用TimeZoneInfo实现时间转换的,使用的是DateTime数据类型。如果改用DateTimeOffset,这个类型对转换为Unix时间戳更加友好。
internal static class DateTimeExtension { private static readonly TimeZoneInfo gmt8 = TimeZoneInfo.CreateCustomTimeZone("GMT+8", TimeSpan.FromHours(8), "China Standard Time", "(UTC+8)China Standard Time"); public static long ToUnixTime(this DateTime datetime) { DateTime dateTimeUtc = datetime; if (datetime.Kind != DateTimeKind.Utc) { dateTimeUtc = datetime.ToUniversalTime(); } if (dateTimeUtc.ToUniversalTime() <= DateTime.UnixEpoch) { return 0; } return (long)(dateTimeUtc - DateTime.UnixEpoch).TotalMilliseconds; } public static DateTime ToDateTime(this long unixTimestamp) { DateTime time = DateTime.UnixEpoch.AddMilliseconds(unixTimestamp); return TimeZoneInfo.ConvertTimeFromUtc(time, gmt8); } public static DateTime ToDateTime(this long unixTimestamp, int timezone) { DateTime time = DateTime.UnixEpoch.AddMilliseconds(unixTimestamp); return time.AddHours(timezone); } }
其实,只要时区是正确的,那么可以也可以使用网友提供的方法进行转换。
// Code from https://stackoverflow.com/questions/5615538/parse-a-date-string-into-a-certain-timezone-supporting-daylight-saving-time public DateTimeOffset ParseDateExactForTimeZone(string dateTime, TimeZoneInfo timezone) { var parsedDateLocal = DateTimeOffset.ParseExact(dateTime, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); var tzOffset = timezone.GetUtcOffset(parsedDateLocal.DateTime); var parsedDateTimeZone = new DateTimeOffset(parsedDateLocal.DateTime, tzOffset); return parsedDateTimeZone; }
实践指南
处理日期与时间的过程中,如果加入了TimeZoneInfo的情况下会使得程序变得非常麻烦,特别是各种TimeZone的Id和名称,不同系统也不统一的情况下,容易出现各种各样的问题。我想的就是避免用它,说说我的处理原则吧。
- 日期时间不使用DateTime类,全部使用DateTimeOffset类型
- 系统的内部处理,全部使用UTC标准时间进行数据表示
- 对于字符串的转换为DataTimeOffset的情况,显式指定时区的小时偏移量
- 直接使用时间的加减,避免使用时区的信息转换导致的代码复杂度增加
- 【可选】如果不用考虑2038年的情况下,可以考虑Unix时间戳简化时间表示
直接贴上我现在使用的代码段,思路就是在强制给字符串表示的时间,加上UTC标准时区信息,然后再修正时差。
public static class DateTimeExtension { public static long? ParseUnixTimeMillisecondsWithTimeZone(string datetimeString, string format = "yyyyMMddHHmmss", int timezoneOffset = 8) { //注意这里非常关键的参数DateTimeStyles.AssumeUniversal,就是设定数据都是UTC的,不管是不是,都强行指定为UTC,然后再按照时区的信息调整为正确的时间。 //给定的数据是东八区时间,但是加上这个参数,实际上的时间就会提前了8个小时,因此需要在后面的数据中直接减去8个小时,如果是其他地区的时间,那么也是一样操作。 if (!DateTimeOffset.TryParseExact(datetimeString, format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTimeOffset time)) return null; DateTimeOffset dateTimeUtcOffset = time.AddHours(-timezoneOffset); return dateTimeUtcOffset.ToUnixTimeMilliseconds(); } public static DateTimeOffset ToDateTime(this long unixTimestamp) => DateTimeOffset.FromUnixTimeMilliseconds(unixTimestamp); }
对于ASP.NET CORE,JSON.NET会自动处理符合ISO8601规范的日期格式,只要指定数据类型为DateTimeOffset,就能够准确转换了。
参考
- https://stackoverflow.com/questions/5615538/parse-a-date-string-into-a-certain-timezone-supporting-daylight-saving-time
- https://stackoverflow.com/questions/62433342/c-sharp-datetime-converting-a-datetimeoffset-to-another-timezone
- https://stackoverflow.com/questions/63153809/parse-string-into-datetimeoffset-while-assuming-timezone
这篇关于NET发布云服务器的时区问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么修改Kafka的JVM参数?-icode9专业技术文章分享
- 2024-12-23线下车企门店如何实现线上线下融合?
- 2024-12-23鸿蒙Next ArkTS编程规范总结
- 2024-12-23物流团队冬至高效运转,哪款办公软件可助力风险评估?
- 2024-12-23优化库存,提升效率:医药企业如何借助看板软件实现仓库智能化
- 2024-12-23项目管理零负担!轻量化看板工具如何助力团队协作
- 2024-12-23电商活动复盘,为何是团队成长的核心环节?
- 2024-12-23鸿蒙Next ArkTS高性能编程实战
- 2024-12-23数据驱动:电商复盘从基础到进阶!
- 2024-12-23从数据到客户:跨境电商如何通过销售跟踪工具提升营销精准度?