时区与时间工具
本页整理框架里和时间戳、UTC、本地时间、多时区上下文相关的可复用工具方法。内容基于当前工作区内的 agilelabs 与 agilelabs.aspnet 实现扫描整理。
适用场景
- API 入参与出参中的 Unix timestamp。
- 数据库存储时间和业务展示时间的转换。
- WorkContext 中的用户时区继承与读取。
- AutoMapper 中的
DateTime、DateTimeOffset、时间戳互转。
核心源码入口
agilelabs/AgileLabs/DateTimeExtension.csagilelabs/AgileLabs/Json/Converters/DateTimeToTimestampJsonConverter.csagilelabs/AgileLabs/Json/Converters/NullableDateTimeToTimestampJsonConverter.csagilelabs.aspnet/src/AgileLabs.WebApp/WorkContexts/DefaultWorkContextCore.csagilelabs.aspnet/src/AgileLabs.EfCore.PostgreSQL/DateTime2DateTimeOffset.csagilelabs.aspnet/src/AgileLabs.EfCore.PostgreSQL/DatetimeMapping.csagilelabs.aspnet/src/AgileLabs.WebApp/AutoMappers/DateTimeOffsetToTimestampTypeConverter.cs
DateTimeExtension 提供的工具
agilelabs/AgileLabs/DateTimeExtension.cs 当前提供了 5 个常用入口:
GetEpochSeconds():把DateTime转成秒级 Unix 时间戳。GetEpochMilliseconds():把DateTime转成毫秒级 Unix 时间戳。FromEpochSeconds():把秒级 Unix 时间戳转回DateTime,返回 UTC 基准时间。FromEpochMilliseconds():把毫秒级 Unix 时间戳转回DateTime,返回 UTC 基准时间。ToChinaStandardTime():当输入是Utc时直接加 8 小时,否则原样返回。
最小示例:
var now = DateTime.UtcNow;
var ts = now.GetEpochMilliseconds();
var restored = ts.FromEpochMilliseconds();
var chinaTime = restored.ToChinaStandardTime();
JSON 层的时间工具
时间相关 JSON converter 位于 agilelabs/AgileLabs/Json/Converters/:
DateTimeToTimestampJsonConverter- 写出时统一使用秒级时间戳。
- 读取时同时兼容 10 位秒级、13 位毫秒级时间戳,以及可解析的时间字符串。
- 时间戳读回后会执行
ToLocalTime()。
NullableDateTimeToTimestampJsonConverter- 处理
DateTime?。 - 写出时仍是秒级时间戳。
- 读取时只直接处理秒级时间戳或可解析字符串。
- 处理
典型用法:
var settings = new JsonSerializerSettings();
settings.Converters.Add(DateTimeToTimestampJsonConverter.Instance);
settings.Converters.Add(NullableDateTimeToTimestampJsonConverter.Instance);
WorkContext 中的时区能力
agilelabs.aspnet 侧的时区上下文主要在 WorkContext:
DefaultWorkContextCore.TimeZoneInfo:根据WorkContextTimeZoneInfo.TimeZoneId解析当前上下文时区。DefaultWorkContextCore.SetTimeZone(...):允许在当前上下文显式切换时区。DefaultWorkContextCoreFactory:创建子上下文时可继承父级时区信息。
这意味着“用户展示时间”不应该只看服务器本地时区,而应优先看当前 WorkContext.TimeZoneInfo。
AutoMapper 与存储层的时间转换
除了基础 DateTime 扩展方法,框架还在映射层提供了两组常见转换:
DateTimeOffsetToTimestampTypeConverter- 位于
agilelabs.aspnet/src/AgileLabs.WebApp/AutoMappers/DateTimeOffsetToTimestampTypeConverter.cs - 提供
DateTimeOffset <-> long的秒级时间戳转换。
- 位于
DateTime2DateTimeOffset- 位于
agilelabs.aspnet/src/AgileLabs.EfCore.PostgreSQL/DateTime2DateTimeOffset.cs - 把
DateTime按 UTC 语义转成DateTimeOffset。 - 把
DateTimeOffset读回DateTime时转换为本地时间。
- 位于
这组能力适合:
- DTO 使用时间戳,领域或持久化层使用
DateTimeOffset。 - PostgreSQL 审计字段统一以 UTC 语义存储。
使用时要注意
DateTimeExtension的时间戳转换依赖TimeZoneInfo.ConvertTimeToUtc(date),调用前要确认DateTime.Kind语义清晰。ToChinaStandardTime()不是通用多时区方案,它只处理 UTC 到中国标准时间这一条路径。DateTimeToTimestampJsonConverter写出的是秒级,不是毫秒级;如果接口约定为毫秒级,需要项目级额外约束。- 显示给用户的时间优先结合
WorkContext.TimeZoneInfo,不要直接把服务器本地时间当用户时间。