Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
/coreclrPublic archive

Commit98e4995

Browse files
authored
Leap Seconds Support (#21420)
* Leap Seconds Support* Address Feedback* More feedback addressing
1 parent2d1a55e commit98e4995

File tree

11 files changed

+531
-110
lines changed

11 files changed

+531
-110
lines changed

‎src/System.Private.CoreLib/System.Private.CoreLib.csproj‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@
141141
<CompileInclude="$(BclSourcesRoot)\System\Collections\Generic\EqualityComparer.cs" />
142142
<CompileInclude="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyDictionary.cs" />
143143
<CompileInclude="$(BclSourcesRoot)\System\Currency.cs" />
144-
<CompileInclude="$(BclSourcesRoot)\System\DateTime.CoreCLR.cs" />
145144
<CompileInclude="$(BclSourcesRoot)\System\DefaultBinder.CanConvert.cs" />
146145
<CompileInclude="$(BclSourcesRoot)\System\Delegate.cs" />
147146
<CompileInclude="$(BclSourcesRoot)\System\Diagnostics\Contracts\Contracts.cs" />
@@ -427,12 +426,14 @@
427426
<CompileInclude="$(BclSourcesRoot)\System\Variant.cs" />
428427
</ItemGroup>
429428
<ItemGroupCondition="'$(TargetsUnix)' == 'true'">
429+
<CompileInclude="$(BclSourcesRoot)\System\DateTime.Unix.cs" />
430430
<CompileInclude="$(BclSourcesRoot)\Interop\Unix\Interop.Libraries.cs" />
431431
<CompileInclude="$(BclSourcesRoot)\System\Globalization\CultureInfo.Unix.cs" />
432432
<CompileInclude="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Unix.cs" />
433433
<CompileInclude="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Unix.cs" />
434434
</ItemGroup>
435435
<ItemGroupCondition="'$(TargetsWindows)' == 'true'">
436+
<CompileInclude="$(BclSourcesRoot)\System\DateTime.Windows.cs" />
436437
<CompileInclude="$(BclSourcesRoot)\Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" />
437438
<CompileInclude="$(BclSourcesRoot)\System\ApplicationModel.Windows.cs" />
438439
<CompileInclude="$(BclSourcesRoot)\System\Diagnostics\DebugProvider.Windows.cs" />
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
usingSystem;
6+
usingSystem.Runtime.InteropServices;
7+
8+
internalpartialclassInterop
9+
{
10+
internalpartialclassNtDll
11+
{
12+
[DllImport(Libraries.NtDll)]
13+
internalstaticunsafeexternintNtQuerySystemInformation(intSystemInformationClass,void*SystemInformation,intSystemInformationLength,uint*ReturnLength);
14+
15+
[StructLayout(LayoutKind.Sequential)]
16+
internalstructSYSTEM_LEAP_SECOND_INFORMATION
17+
{
18+
publicboolEnabled;
19+
publicuintFlags;
20+
}
21+
22+
internalconstintSystemLeapSecondInformation=206;
23+
}
24+
}

‎src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@
859859
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs" />
860860
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Idna.cs"Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
861861
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Normalization.cs"Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
862+
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\NtDll\Interop.NtQuerySystemInformation.cs"Condition="'$(EnableWinRT)' != 'true'" />
862863
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\Ole32\Interop.CoCreateGuid.cs" />
863864
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
864865
<CompileInclude="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />

‎src/System.Private.CoreLib/shared/System/DateTime.cs‎

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ public DateTime(int year, int month, int day, Calendar calendar)
196196
//
197197
publicDateTime(intyear,intmonth,intday,inthour,intminute,intsecond)
198198
{
199+
if(second==60&&s_systemSupportsLeapSeconds&&IsValidTimeWithLeapSeconds(year,month,day,hour,minute,second,DateTimeKind.Unspecified))
200+
{
201+
// if we have leap second (second = 60) then we'll need to check if it is valid time.
202+
// if it is valid, then we adjust the second to 59 so DateTime will consider this second is last second
203+
// in the specified minute.
204+
// if it is not valid time, we'll eventually throw.
205+
second=59;
206+
}
199207
_dateData=(ulong)(DateToTicks(year,month,day)+TimeToTicks(hour,minute,second));
200208
}
201209

@@ -205,6 +213,16 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
205213
{
206214
thrownewArgumentException(SR.Argument_InvalidDateTimeKind,nameof(kind));
207215
}
216+
217+
if(second==60&&s_systemSupportsLeapSeconds&&IsValidTimeWithLeapSeconds(year,month,day,hour,minute,second,kind))
218+
{
219+
// if we have leap second (second = 60) then we'll need to check if it is valid time.
220+
// if it is valid, then we adjust the second to 59 so DateTime will consider this second is last second
221+
// in the specified minute.
222+
// if it is not valid time, we'll eventually throw.
223+
second=59;
224+
}
225+
208226
longticks=DateToTicks(year,month,day)+TimeToTicks(hour,minute,second);
209227
_dateData=((ulong)ticks|((ulong)kind<<KindShift));
210228
}
@@ -216,7 +234,24 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
216234
{
217235
if(calendar==null)
218236
thrownewArgumentNullException(nameof(calendar));
237+
238+
intoriginalSecond=second;
239+
if(second==60&&s_systemSupportsLeapSeconds)
240+
{
241+
// Reset the second value now and then we'll validate it later when we get the final Gregorian date.
242+
second=59;
243+
}
244+
219245
_dateData=(ulong)calendar.ToDateTime(year,month,day,hour,minute,second,0).Ticks;
246+
247+
if(originalSecond==60)
248+
{
249+
DateTimedt=newDateTime(_dateData);
250+
if(!IsValidTimeWithLeapSeconds(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Minute,60,DateTimeKind.Unspecified))
251+
{
252+
thrownewArgumentOutOfRangeException(null,SR.ArgumentOutOfRange_BadHourMinuteSecond);
253+
}
254+
}
220255
}
221256

222257
// Constructs a DateTime from a given year, month, day, hour,
@@ -228,6 +263,16 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
228263
{
229264
thrownewArgumentOutOfRangeException(nameof(millisecond),SR.Format(SR.ArgumentOutOfRange_Range,0,MillisPerSecond-1));
230265
}
266+
267+
if(second==60&&s_systemSupportsLeapSeconds&&IsValidTimeWithLeapSeconds(year,month,day,hour,minute,second,DateTimeKind.Unspecified))
268+
{
269+
// if we have leap second (second = 60) then we'll need to check if it is valid time.
270+
// if it is valid, then we adjust the second to 59 so DateTime will consider this second is last second
271+
// in the specified minute.
272+
// if it is not valid time, we'll eventually throw.
273+
second=59;
274+
}
275+
231276
longticks=DateToTicks(year,month,day)+TimeToTicks(hour,minute,second);
232277
ticks+=millisecond*TicksPerMillisecond;
233278
if(ticks<MinTicks||ticks>MaxTicks)
@@ -245,6 +290,16 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
245290
{
246291
thrownewArgumentException(SR.Argument_InvalidDateTimeKind,nameof(kind));
247292
}
293+
294+
if(second==60&&s_systemSupportsLeapSeconds&&IsValidTimeWithLeapSeconds(year,month,day,hour,minute,second,kind))
295+
{
296+
// if we have leap second (second = 60) then we'll need to check if it is valid time.
297+
// if it is valid, then we adjust the second to 59 so DateTime will consider this second is last second
298+
// in the specified minute.
299+
// if it is not valid time, we'll eventually throw.
300+
second=59;
301+
}
302+
248303
longticks=DateToTicks(year,month,day)+TimeToTicks(hour,minute,second);
249304
ticks+=millisecond*TicksPerMillisecond;
250305
if(ticks<MinTicks||ticks>MaxTicks)
@@ -263,11 +318,28 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
263318
{
264319
thrownewArgumentOutOfRangeException(nameof(millisecond),SR.Format(SR.ArgumentOutOfRange_Range,0,MillisPerSecond-1));
265320
}
321+
322+
intoriginalSecond=second;
323+
if(second==60&&s_systemSupportsLeapSeconds)
324+
{
325+
// Reset the second value now and then we'll validate it later when we get the final Gregorian date.
326+
second=59;
327+
}
328+
266329
longticks=calendar.ToDateTime(year,month,day,hour,minute,second,0).Ticks;
267330
ticks+=millisecond*TicksPerMillisecond;
268331
if(ticks<MinTicks||ticks>MaxTicks)
269332
thrownewArgumentException(SR.Arg_DateTimeRange);
270333
_dateData=(ulong)ticks;
334+
335+
if(originalSecond==60)
336+
{
337+
DateTimedt=newDateTime(_dateData);
338+
if(!IsValidTimeWithLeapSeconds(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Minute,60,DateTimeKind.Unspecified))
339+
{
340+
thrownewArgumentOutOfRangeException(null,SR.ArgumentOutOfRange_BadHourMinuteSecond);
341+
}
342+
}
271343
}
272344

273345
publicDateTime(intyear,intmonth,intday,inthour,intminute,intsecond,intmillisecond,Calendarcalendar,DateTimeKindkind)
@@ -282,11 +354,28 @@ public DateTime(int year, int month, int day, int hour, int minute, int second,
282354
{
283355
thrownewArgumentException(SR.Argument_InvalidDateTimeKind,nameof(kind));
284356
}
357+
358+
intoriginalSecond=second;
359+
if(second==60&&s_systemSupportsLeapSeconds)
360+
{
361+
// Reset the second value now and then we'll validate it later when we get the final Gregorian date.
362+
second=59;
363+
}
364+
285365
longticks=calendar.ToDateTime(year,month,day,hour,minute,second,0).Ticks;
286366
ticks+=millisecond*TicksPerMillisecond;
287367
if(ticks<MinTicks||ticks>MaxTicks)
288368
thrownewArgumentException(SR.Arg_DateTimeRange);
289369
_dateData=((ulong)ticks|((ulong)kind<<KindShift));
370+
371+
if(originalSecond==60)
372+
{
373+
DateTimedt=newDateTime(_dateData);
374+
if(!IsValidTimeWithLeapSeconds(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Minute,60,kind))
375+
{
376+
thrownewArgumentOutOfRangeException(null,SR.ArgumentOutOfRange_BadHourMinuteSecond);
377+
}
378+
}
290379
}
291380

292381
privateDateTime(SerializationInfoinfo,StreamingContextcontext)
@@ -338,8 +427,6 @@ private DateTime(SerializationInfo info, StreamingContext context)
338427
}
339428
}
340429

341-
342-
343430
internallongInternalTicks
344431
{
345432
get
@@ -722,6 +809,11 @@ public static DateTime FromFileTimeUtc(long fileTime)
722809
thrownewArgumentOutOfRangeException(nameof(fileTime),SR.ArgumentOutOfRange_FileTimeInvalid);
723810
}
724811

812+
if(s_systemSupportsLeapSeconds)
813+
{
814+
returnFromFileTimeLeapSecondsAware(fileTime);
815+
}
816+
725817
// This is the ticks in Universal time for this fileTime.
726818
longuniversalTicks=fileTime+FileTimeOffset;
727819
returnnewDateTime(universalTicks,DateTimeKind.Utc);
@@ -1223,11 +1315,18 @@ public long ToFileTimeUtc()
12231315
{
12241316
// Treats the input as universal if it is not specified
12251317
longticks=((InternalKind&LocalMask)!=0)?ToUniversalTime().InternalTicks:this.InternalTicks;
1318+
1319+
if(s_systemSupportsLeapSeconds)
1320+
{
1321+
returnToFileTimeLeapSecondsAware(ticks);
1322+
}
1323+
12261324
ticks-=FileTimeOffset;
12271325
if(ticks<0)
12281326
{
12291327
thrownewArgumentOutOfRangeException(null,SR.ArgumentOutOfRange_FileTimeInvalid);
12301328
}
1329+
12311330
returnticks;
12321331
}
12331332

@@ -1574,14 +1673,32 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut
15741673
{
15751674
returnfalse;
15761675
}
1577-
if(hour<0||hour>=24||minute<0||minute>=60||second<0||second>=60)
1676+
if(hour<0||hour>=24||minute<0||minute>=60||second<0||second>60)
15781677
{
15791678
returnfalse;
15801679
}
15811680
if(millisecond<0||millisecond>=MillisPerSecond)
15821681
{
15831682
returnfalse;
15841683
}
1684+
1685+
if(second==60)
1686+
{
1687+
if(s_systemSupportsLeapSeconds&&IsValidTimeWithLeapSeconds(year,month,day,hour,minute,second,DateTimeKind.Unspecified))
1688+
{
1689+
// if we have leap second (second = 60) then we'll need to check if it is valid time.
1690+
// if it is valid, then we adjust the second to 59 so DateTime will consider this second is last second
1691+
// of this minute.
1692+
// if it is not valid time, we'll eventually throw.
1693+
// although this is unspecified datetime kind, we'll assume the passed time is UTC to check the leap seconds.
1694+
second=59;
1695+
}
1696+
else
1697+
{
1698+
returnfalse;
1699+
}
1700+
}
1701+
15851702
longticks=DateToTicks(year,month,day)+TimeToTicks(hour,minute,second);
15861703

15871704
ticks+=millisecond*TicksPerMillisecond;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp