如何计算 DateTime.UtcNow 值

本文关键字:DateTime UtcNow 计算 何计算 | 更新日期: 2023-09-27 18:33:16

.Net 究竟从哪里获取此值?这是来自 GetSystemTimeAsFileTime 的值吗?那么这个值是如何计算的呢?它是否以某种方式基于 QPC 值?

如何计算 DateTime.UtcNow 值

UtcNow定义如下。为简洁起见,剥离了属性)

public static DateTime UtcNow
{
    get
    {
        return new DateTime((ulong) ((GetSystemTimeAsFileTime() + 0x701ce1722770000L) | 0x4000000000000000L));
    }
}

GetSystemTimeAsFileTime定义为内部调用。

[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical]
internal static extern long GetSystemTimeAsFileTime();

反射器也帮不上忙了,让我们深入研究sscli。

GetSystemTimeAsFileTime映射到SystemNative::__GetSystemTimeAsFileTime(ecall.cpp)

FCFuncStart(gDateTimeFuncs)
    FCFuncElement("GetSystemTimeAsFileTime", SystemNative::__GetSystemTimeAsFileTime)
FCFuncEnd()

最后SystemNative::__GetSystemTimeAsFileTime实现如下(comsystem.cpp)

FCIMPL0(INT64, SystemNative::__GetSystemTimeAsFileTime)
{
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;
    INT64 timestamp;
    ::GetSystemTimeAsFileTime((FILETIME*)&timestamp);
#if BIGENDIAN
    timestamp = (INT64)(((UINT64)timestamp >> 32) | ((UINT64)timestamp << 32));
#endif
    return timestamp;
}
FCIMPLEND;

因此,UtcNow只是GetSystemTimeAsFileTime函数的包装器,并处理BigEndian的情况。

在微软发布其开源操作系统之前,我们不能走得更远:)

DateTime.UtcNow是通过

从当前日期/时间中减去主机操作系统时区的偏移量来计算的。

是的,在ILSpy内部查找它调用GetSystemTimeAsFileTime:

[SecurityCritical]
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern long GetSystemTimeAsFileTime();

要执行此操作,请使用TimeZoneInfo.Local手动拉取当前时区,这将为您提供一个BaseUtcOffset,然后您可以从当前日期/时间中减去该偏移量,例如:

TimeZoneInfo tz_info = TimeZoneInfo.Local;
TimeSpan offset = tz_info.BaseUtcOffset;
DateTime now = DateTime.Now;
DateTime utc_now = now.Subtract(offset);

请注意,这些值作为操作系统设置存储在注册表及其他版本中。请记住,当您安装 Windows 时,您可以选择您想要的时区。如果你勇敢,你可以在这里找到一些信息:

HKEY_LOCAL_MACHINE'SOFTWARE'Microsoft'Windows NT'CurrentVersion'Time Zones

MSDN博客上有一篇关于时区等的优秀文章 - http://blogs.msdn.com/b/bclteam/archive/2007/06/07/exploring-windows-time-zones-with-system-timezoneinfo-josh-free.aspx

Whow.人们检查 IL 而不是源代码。

日期时间类的源位于 http://referencesource.microsoft.com/#mscorlib/system/datetime.cs,df6b1eba7461813b

UtcNow从959号线开始。

无需使用反汇编器、反射器或其他任何东西 - 您可以看到编写的代码。