Skip to content

Commit 1d272e6

Browse files
authored
Expose the constants in TimeSpan (#103993)
Publicly expose the useful constants that `TimeSpan` had internally declared since they're rooted in hard reality and not changeable, and quite useful elsewhere. Everything is a `long` except `HoursPerDay` because that is useful in many non-TimeSpan contexts and rarely would overflow. Added /// documentation for newly public constants and updated _System.Runtime.cs_ assembly API reference. Use the newly exposed values in all the runtime places similar constants are declared in runtime **EXCEPT** did not use the `TimeSpan` constant in _EventLogInternal.cs_ since that source is also built for older frameworks, leave existing internal constant. In _Calendar.cs_, use an `int` cast at the call-sites to `Add` method to prevent performance degradation, these calls are known not to overflow. Fixes #94545
1 parent 9d008f4 commit 1d272e6

File tree

20 files changed

+291
-195
lines changed

20 files changed

+291
-195
lines changed

src/libraries/System.Diagnostics.EventLog/src/System/Diagnostics/EventLogInternal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ internal sealed class EventLogInternal : IDisposable, ISupportInitialize
5555

5656
private const string EventLogKey = "SYSTEM\\CurrentControlSet\\Services\\EventLog";
5757
private const string eventLogMutexName = "netfxeventlog.1.0";
58-
private const int SecondsPerDay = 60 * 60 * 24;
58+
private const int SecondsPerDay = 60 * 60 * 24; // can't pull in the new TimeSpan constant because this builds in older CLR versions
5959

6060
private const int Flag_notifying = 0x1; // keeps track of whether we're notifying our listeners - to prevent double notifications
6161
private const int Flag_forwards = 0x2; // whether the cache contains entries in forwards order (true) or backwards (false)

src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private static unsafe DateTime FromFileTimeLeapSecondsAware(ulong fileTime)
7777
{
7878
throw new ArgumentOutOfRangeException(nameof(fileTime), SR.ArgumentOutOfRange_DateTimeBadTicks);
7979
}
80-
return CreateDateTimeFromSystemTime(in time, fileTime % TicksPerMillisecond);
80+
return CreateDateTimeFromSystemTime(in time, fileTime % TimeSpan.TicksPerMillisecond);
8181
}
8282

8383
private static unsafe ulong ToFileTimeLeapSecondsAware(long ticks)
@@ -112,20 +112,20 @@ private static DateTime CreateDateTimeFromSystemTime(in Interop.Kernel32.SYSTEMT
112112
ReadOnlySpan<uint> days = IsLeapYear((int)year) ? DaysToMonth366 : DaysToMonth365;
113113
int month = time.Month - 1;
114114
uint n = DaysToYear(year) + days[month] + time.Day - 1;
115-
ulong ticks = n * (ulong)TicksPerDay;
115+
ulong ticks = n * (ulong)TimeSpan.TicksPerDay;
116116

117-
ticks += time.Hour * (ulong)TicksPerHour;
118-
ticks += time.Minute * (ulong)TicksPerMinute;
117+
ticks += time.Hour * (ulong)TimeSpan.TicksPerHour;
118+
ticks += time.Minute * (ulong)TimeSpan.TicksPerMinute;
119119
uint second = time.Second;
120120
if (second <= 59)
121121
{
122-
ulong tmp = second * (uint)TicksPerSecond + time.Milliseconds * (uint)TicksPerMillisecond + hundredNanoSecond;
122+
ulong tmp = second * (uint)TimeSpan.TicksPerSecond + time.Milliseconds * (uint)TimeSpan.TicksPerMillisecond + hundredNanoSecond;
123123
return new DateTime(ticks + tmp | KindUtc);
124124
}
125125

126126
// we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation.
127127
// we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds
128-
ticks += TicksPerMinute - 1 | KindUtc;
128+
ticks += TimeSpan.TicksPerMinute - 1 | KindUtc;
129129
return new DateTime(ticks);
130130
}
131131

@@ -166,7 +166,7 @@ private static unsafe bool GetSystemSupportsLeapSeconds()
166166
((delegate* unmanaged[SuppressGCTransition]<long*, void>)pfnGetSystemTime)(&systemTimeResult);
167167
((delegate* unmanaged[SuppressGCTransition]<long*, void>)pfnGetSystemTimePrecise)(&preciseSystemTimeResult);
168168

169-
if (Math.Abs(preciseSystemTimeResult - systemTimeResult) <= 100 * TicksPerMillisecond)
169+
if (Math.Abs(preciseSystemTimeResult - systemTimeResult) <= 100 * TimeSpan.TicksPerMillisecond)
170170
{
171171
pfnGetSystemTime = pfnGetSystemTimePrecise; // use the precise version
172172
break;
@@ -194,7 +194,7 @@ private static unsafe DateTime UpdateLeapSecondCacheAndReturnUtcNow()
194194
// cache will return incorrect values.
195195

196196
Debug.Assert(SystemSupportsLeapSeconds);
197-
Debug.Assert(LeapSecondCache.ValidityPeriodInTicks < TicksPerDay - TicksPerSecond, "Leap second cache validity window should be less than 23:59:59.");
197+
Debug.Assert(LeapSecondCache.ValidityPeriodInTicks < TimeSpan.TicksPerDay - TimeSpan.TicksPerSecond, "Leap second cache validity window should be less than 23:59:59.");
198198

199199
ulong fileTimeNow;
200200
LeapSecondCache.s_pfnGetSystemTimeAsFileTime(&fileTimeNow);
@@ -203,7 +203,7 @@ private static unsafe DateTime UpdateLeapSecondCacheAndReturnUtcNow()
203203
// First, convert the FILETIME to a SYSTEMTIME.
204204

205205
Interop.Kernel32.SYSTEMTIME systemTimeNow;
206-
ulong hundredNanoSecondNow = fileTimeNow % TicksPerMillisecond;
206+
ulong hundredNanoSecondNow = fileTimeNow % TimeSpan.TicksPerMillisecond;
207207

208208
// We need the FILETIME and the SYSTEMTIME to reflect each other's values.
209209
// If FileTimeToSystemTime fails, call GetSystemTime and try again until it succeeds.
@@ -267,7 +267,7 @@ private static unsafe DateTime UpdateLeapSecondCacheAndReturnUtcNow()
267267
}
268268

269269
// StartOfValidityWindow = MidnightUtc + 23:59:59 - ValidityPeriod
270-
fileTimeAtStartOfValidityWindow = fileTimeAtBeginningOfDay + (TicksPerDay - TicksPerSecond) - LeapSecondCache.ValidityPeriodInTicks;
270+
fileTimeAtStartOfValidityWindow = fileTimeAtBeginningOfDay + (TimeSpan.TicksPerDay - TimeSpan.TicksPerSecond) - LeapSecondCache.ValidityPeriodInTicks;
271271
if (fileTimeNow - fileTimeAtStartOfValidityWindow >= LeapSecondCache.ValidityPeriodInTicks)
272272
{
273273
// If we're inside this block, then we slid the validity window back so far that the current time is no
@@ -295,7 +295,7 @@ private static unsafe DateTime UpdateLeapSecondCacheAndReturnUtcNow()
295295
return CreateDateTimeFromSystemTime(systemTimeNow, hundredNanoSecondNow);
296296
}
297297

298-
dotnetDateDataAtStartOfValidityWindow = CreateDateTimeFromSystemTime(systemTimeAtBeginningOfDay, 0)._dateData + (TicksPerDay - TicksPerSecond) - LeapSecondCache.ValidityPeriodInTicks;
298+
dotnetDateDataAtStartOfValidityWindow = CreateDateTimeFromSystemTime(systemTimeAtBeginningOfDay, 0)._dateData + (TimeSpan.TicksPerDay - TimeSpan.TicksPerSecond) - LeapSecondCache.ValidityPeriodInTicks;
299299
}
300300

301301
// Finally, update the cache and return UtcNow.
@@ -330,7 +330,7 @@ static DateTime LowGranularityNonCachedFallback()
330330
private sealed class LeapSecondCache
331331
{
332332
// The length of the validity window. Must be less than 23:59:59.
333-
internal const ulong ValidityPeriodInTicks = TicksPerMinute * 5;
333+
internal const ulong ValidityPeriodInTicks = TimeSpan.TicksPerMinute * 5;
334334

335335
// The FILETIME value at the beginning of the validity window.
336336
internal ulong OSFileTimeTicksAtStartOfValidityWindow;

0 commit comments

Comments
 (0)