- Notifications
You must be signed in to change notification settings - Fork2.6k
Leap Seconds Support#21420
Uh oh!
There was an error while loading.Please reload this page.
Leap Seconds Support#21420
Changes from1 commit
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -432,6 +432,7 @@ | ||
| </ItemGroup> | ||
| <ItemGroupCondition="'$(TargetsWindows)' == 'true'"> | ||
| <CompileInclude="$(BclSourcesRoot)\System\DateTime.Windows.cs" /> | ||
| <CompileInclude="shared/Interop/Windows/NtDll/Interop.NtQuerySystemInformation.cs" /> | ||
| ||
| <CompileInclude="$(BclSourcesRoot)\Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" /> | ||
| <CompileInclude="$(BclSourcesRoot)\System\ApplicationModel.Windows.cs" /> | ||
| <CompileInclude="$(BclSourcesRoot)\System\Diagnostics\DebugProvider.Windows.cs" /> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
| // See the LICENSE file in the project root for more information. | ||
| usingSystem; | ||
| usingSystem.Runtime.InteropServices; | ||
| internalpartialclassInterop | ||
| { | ||
| internalpartialclassNtDll | ||
| { | ||
| [DllImport(Libraries.NtDll)] | ||
| internalstaticunsafeexternintNtQuerySystemInformation(intSystemInformationClass,void*SystemInformation,intSystemInformationLength,uint*ReturnLength); | ||
| [StructLayout(LayoutKind.Sequential)] | ||
| internalstructSYSTEM_LEAP_SECOND_INFORMATION | ||
| { | ||
| publicboolEnabled; | ||
| publicuintFlags; | ||
| } | ||
| internalconstintSystemLeapSecondInformation=206; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -9,24 +9,20 @@ namespace System | ||
| { | ||
| public readonly partial struct DateTime | ||
| { | ||
| internal static readonly bools_systemSupportsLeapSeconds =SystemSupportsLeapSeconds(); | ||
| public static DateTime UtcNow | ||
| { | ||
| get | ||
| { | ||
| if (s_systemSupportsLeapSeconds) | ||
| { | ||
| FullSystemTime time; | ||
| GetSystemTimeWithLeapSecondsHandling(out time); | ||
| return CreateDateTimeFromSystemTime(in time); | ||
| } | ||
| return new DateTime(((ulong)(GetSystemTimeAsFileTime() + FileTimeOffset)) | KindUtc); | ||
| } | ||
| } | ||
| @@ -37,7 +33,7 @@ public static DateTime FromFileTimeUtc(long fileTime) | ||
| throw new ArgumentOutOfRangeException(nameof(fileTime), SR.ArgumentOutOfRange_FileTimeInvalid); | ||
| } | ||
| if (s_systemSupportsLeapSeconds) | ||
| { | ||
| return InternalFromFileTime(fileTime); | ||
| } | ||
| @@ -51,7 +47,7 @@ public long ToFileTimeUtc() { | ||
| // Treats the input as universal if it is not specified | ||
| long ticks = ((InternalKind & LocalMask) != 0) ? ToUniversalTime().InternalTicks : this.InternalTicks; | ||
| if (s_systemSupportsLeapSeconds) | ||
| { | ||
| return InternalToFileTime(ticks); | ||
| } | ||
| @@ -71,64 +67,71 @@ internal static bool IsValidTimeWithLeapSeconds(int year, int month, int day, in | ||
| switch (kind) | ||
| { | ||
| case DateTimeKind.Local: return ValidateSystemTime(ref time.systemTime, localTime: true); | ||
| case DateTimeKind.Utc: return ValidateSystemTime(ref time.systemTime, localTime: false); | ||
| default: | ||
| return ValidateSystemTime(ref time.systemTime, localTime: true) || ValidateSystemTime(ref time.systemTime, localTime: false); | ||
| } | ||
| } | ||
| internal static DateTime InternalFromFileTime(long fileTime) | ||
| { | ||
| FullSystemTime time; | ||
| if (SystemFileTimeToSystemTime(fileTime,out time)) | ||
| ||
| { | ||
| time.hundredNanoSecond = fileTime % TicksPerMillisecond; | ||
| return CreateDateTimeFromSystemTime(in time); | ||
| } | ||
| throw new ArgumentOutOfRangeException("fileTime", SR.ArgumentOutOfRange_DateTimeBadTicks); | ||
| } | ||
| internal static long InternalToFileTime(long ticks) | ||
| { | ||
| long fileTime; | ||
| FullSystemTime time = new FullSystemTime(ticks); | ||
| if (SystemTimeToSystemFileTime(ref time.systemTime, out fileTime)) | ||
| ||
| { | ||
| return fileTime + ticks % TicksPerMillisecond; | ||
| } | ||
| throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_FileTimeInvalid); | ||
| } | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| internal static DateTime CreateDateTimeFromSystemTime(in FullSystemTime time) | ||
| { | ||
| long ticks = DateToTicks(time.systemTime.Year, time.systemTime.Month, time.systemTime.Day); | ||
| ticks += TimeToTicks(time.systemTime.Hour, time.systemTime.Minute, time.systemTime.Second); | ||
| ticks += time.systemTime.Milliseconds * TicksPerMillisecond; | ||
| ticks += time.hundredNanoSecond; | ||
| return new DateTime( ((UInt64)(ticks)) | KindUtc); | ||
| } | ||
| private static unsafe bool SystemSupportsLeapSeconds() | ||
| { | ||
| Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION slsi = new Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION(); | ||
| return Interop.NtDll.NtQuerySystemInformation( | ||
| Interop.NtDll.SystemLeapSecondInformation, | ||
| (void *) &slsi, | ||
| sizeof(Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION), | ||
| null) == 0 && slsi.Enabled; | ||
| } | ||
| // FullSystemTime struct is the SYSTEMTIME struct with extra hundredNanoSecond field to store more precise time. | ||
| [StructLayout(LayoutKind.Sequential)] | ||
| internal struct FullSystemTime | ||
| { | ||
| internal FullSystemTime(int year, int month, DayOfWeek dayOfWeek, int day, int hour, int minute, int second) | ||
| { | ||
| systemTime.Year = (ushort) year; | ||
| systemTime.Month = (ushort) month; | ||
| systemTime.DayOfWeek = (ushort) dayOfWeek; | ||
| systemTime.Day = (ushort) day; | ||
| systemTime.Hour = (ushort) hour; | ||
| systemTime.Minute = (ushort) minute; | ||
| systemTime.Second = (ushort) second; | ||
| systemTime.Milliseconds = 0; | ||
| hundredNanoSecond = 0; | ||
| } | ||
| @@ -139,42 +142,32 @@ internal FullSystemTime(long ticks) | ||
| int year, month, day; | ||
| dt.GetDatePart(out year, out month, out day); | ||
| systemTime.Year = (ushort) year; | ||
| systemTime.Month = (ushort) month; | ||
| systemTime.DayOfWeek = (ushort) dt.DayOfWeek; | ||
| systemTime.Day = (ushort) day; | ||
| systemTime.Hour = (ushort) dt.Hour; | ||
| systemTime.Minute = (ushort) dt.Minute; | ||
| systemTime.Second = (ushort) dt.Second; | ||
| systemTime.Milliseconds = (ushort) dt.Millisecond; | ||
| hundredNanoSecond = 0; | ||
| } | ||
| internal Interop.Kernel32.SYSTEMTIME systemTime; | ||
| ||
| internal long hundredNanoSecond; | ||
| }; | ||
| [MethodImplAttribute(MethodImplOptions.InternalCall)] | ||
| internal static extern bool ValidateSystemTime(ref Interop.Kernel32.SYSTEMTIME time, bool localTime); | ||
| ||
| [MethodImplAttribute(MethodImplOptions.InternalCall)] | ||
| internal static extern bool SystemFileTimeToSystemTime(long fileTime,out FullSystemTime time); | ||
| ||
| [MethodImplAttribute(MethodImplOptions.InternalCall)] | ||
| internal static extern void GetSystemTimeWithLeapSecondsHandling(out FullSystemTime time); | ||
| [MethodImplAttribute(MethodImplOptions.InternalCall)] | ||
| internal static extern bool SystemTimeToSystemFileTime(refInterop.Kernel32.SYSTEMTIME time,out long fileTime); | ||
| ||
| [MethodImplAttribute(MethodImplOptions.InternalCall)] | ||
| internal static extern long GetSystemTimeAsFileTime(); | ||
Uh oh!
There was an error while loading.Please reload this page.