-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Expose the remaining const values in TimeSpan #94545
Comments
Tagging subscribers to this area: @dotnet/area-system-datetime Issue DetailsBackground and motivationIn the There are also a bunch more that are These values should be exposed publicly on the TimeSpan class. Note: NOT suggesting we expose the truly API Proposalnamespace System.Collections.Generic;
public class TimeSpan: // elided details
{
// more elision
public const long MicrosecondsPerMillisecond = TicksPerMillisecond / TicksPerMicrosecond; // 1,000
public const long MicrosecondsPerSecond = TicksPerSecond / TicksPerMicrosecond; // 1,000,000
public const long MicrosecondsPerMinute = TicksPerMinute / TicksPerMicrosecond; // 60,000,000
public const long MicrosecondsPerHour = TicksPerHour / TicksPerMicrosecond; // 3,600,000,000
public const long MicrosecondsPerDay = TicksPerDay / TicksPerMicrosecond; // 86,400,000,000
public const long MillisecondsPerSecond = TicksPerSecond / TicksPerMillisecond; // 1,000
public const long MillisecondsPerMinute = TicksPerMinute / TicksPerMillisecond; // 60,000
public const long MillisecondsPerHour = TicksPerHour / TicksPerMillisecond; // 3,600,000
public const long MillisecondsPerDay = TicksPerDay / TicksPerMillisecond; // 86,400,000
public const long SecondsPerMinute = TicksPerMinute / TicksPerSecond; // 60
public const long SecondsPerHour = TicksPerHour / TicksPerSecond; // 3,600
public const long SecondsPerDay = TicksPerDay / TicksPerSecond; // 86,400
public const long MinutesPerHour = TicksPerHour / TicksPerMinute; // 60
public const long MinutesPerDay = TicksPerDay / TicksPerMinute; // 1,440
public const long HoursPerDay = TicksPerDay / TicksPerHour; // 24
} API Usageif (TimeSpan.MinutesPerHour * numHours) > TimeSpan.MinutesPerDay * 7)
Console.WriteLine("That's really weeks"); Alternative DesignsN/A RisksSince these are compile-time constant values, there would be no runtime cost in either memory or execution overhead. Additionally they would centralize basic real-world facts to one logical location (TimeSpan).
|
Make the useful constants that TimeSpan has internally declare public because they're rooted in hard reality and not changeable, and quite useful elsewhere. Fixes dotnet#94545
Make the useful constants that TimeSpan has internally declare public because they're rooted in hard reality and not changeable, and quite useful elsewhere. Fixes dotnet#94545
Is this something we can add to the API review? |
CC. @tarekgh, this is a relatively simple ask and I know I've had to redefine such constants myself in personal projects to help with various extension methods or other time related structs used (such as a |
I am fine to proceed with the proposal. I don't have any feedback as the proposal looks good to me as it is. I'll mark this as ready for review. |
Should I reopen the PR or start a new one? :) |
@IDisposable please wait till the issue gets reviewed by the design committee and then we can reopen the PR. Thanks! |
namespace System.Collections.Generic;
public partial class TimeSpan
{
public const int MicrosecondsPerMillisecond = TicksPerMillisecond / TicksPerMicrosecond; // 1,000
public const int MicrosecondsPerSecond = TicksPerSecond / TicksPerMicrosecond; // 1,000,000
public const int MicrosecondsPerMinute = TicksPerMinute / TicksPerMicrosecond; // 60,000,000
public const long MicrosecondsPerHour = TicksPerHour / TicksPerMicrosecond; // 3,600,000,000
public const long MicrosecondsPerDay = TicksPerDay / TicksPerMicrosecond; // 86,400,000,000
public const int MillisecondsPerSecond = TicksPerSecond / TicksPerMillisecond; // 1,000
public const int MillisecondsPerMinute = TicksPerMinute / TicksPerMillisecond; // 60,000
public const int MillisecondsPerHour = TicksPerHour / TicksPerMillisecond; // 3,600,000
public const int MillisecondsPerDay = TicksPerDay / TicksPerMillisecond; // 86,400,000
public const int SecondsPerMinute = TicksPerMinute / TicksPerSecond; // 60
public const int SecondsPerHour = TicksPerHour / TicksPerSecond; // 3,600
public const int SecondsPerDay = TicksPerDay / TicksPerSecond; // 86,400
public const int MinutesPerHour = TicksPerHour / TicksPerMinute; // 60
public const int MinutesPerDay = TicksPerDay / TicksPerMinute; // 1,440
public const int HoursPerDay = TicksPerDay / TicksPerHour; // 24
} |
What was the underlying reason to not expose these when they were first introduced? Was it just a matter of YAGNI, or was there more to it? |
In general, I certainly agree, I was just adjusting the visibility of what was already there... so moving them to |
Usually, such constants get introduced when implementing other approved features. To expose anything, it needs to go as a separate proposal to design review it. That is what happened here. |
If we find this is problematic, then please comment back and we can keep them as I can easily get the sign-off for that over e-mail and just chalk it up to a consideration no one thought about in the 60s it took to review the APIs 😆 |
I merged the changes but I missed your comment #94545 (comment). We went with |
Preparing a change to make the smaller constants
|
@IDisposable let's apply the approved proposal #94545 (comment) and then we can track any further changes to bring it back to the design review. |
New PR #103721 |
Based on the domain (the While that's not so nice for namespace System.Collections.Generic;
public class TimeSpan: // elided details
{
// more elision
public const long MicrosecondsPerMillisecond = TicksPerMillisecond / TicksPerMicrosecond; // 1,000
public const long MicrosecondsPerSecond = TicksPerSecond / TicksPerMicrosecond; // 1,000,000
public const long MicrosecondsPerMinute = TicksPerMinute / TicksPerMicrosecond; // 60,000,000
public const long MicrosecondsPerHour = TicksPerHour / TicksPerMicrosecond; // 3,600,000,000
public const long MicrosecondsPerDay = TicksPerDay / TicksPerMicrosecond; // 86,400,000,000
public const long MillisecondsPerSecond = TicksPerSecond / TicksPerMillisecond; // 1,000
public const long MillisecondsPerMinute = TicksPerMinute / TicksPerMillisecond; // 60,000
public const long MillisecondsPerHour = TicksPerHour / TicksPerMillisecond; // 3,600,000
public const long MillisecondsPerDay = TicksPerDay / TicksPerMillisecond; // 86,400,000
public const long SecondsPerMinute = TicksPerMinute / TicksPerSecond; // 60
public const long SecondsPerHour = TicksPerHour / TicksPerSecond; // 3,600
public const long SecondsPerDay = TicksPerDay / TicksPerSecond; // 86,400
public const long MinutesPerHour = TicksPerHour / TicksPerMinute; // 60
public const long MinutesPerDay = TicksPerDay / TicksPerMinute; // 1,440
public const int HoursPerDay = TicksPerDay / TicksPerHour; // 24
} |
That makes perfect sense, let me know when/what the final should be and I will resubmit |
You should feel free to submit a PR matching it at any time now, we're in agreement as to the handling here now. |
It is ready now so you can resurrect or create a new PR now. |
Working on it... do we have a decision about the casting at call-site or modifying the parameters type as mentioned here? We had settled on casting at the call site, last I remember... and suspect we should go that route now. |
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 dotnet#94545
PR #103993 has hopefully final iteration :) |
Edited By @tarekgh
This proposal has been approved before #94545 (comment). There was some feedback from @tannergooding and @IDisposable.
@tannergooding said: the concern I raised is that there are scenarios this can cause problems since
days * TimeSpan.HoursPerDay
could overflow. For example, ifdays > 89,478,485
then this will overflow to a negativeint
.HoursPerDay
happens to be the only case where it is "sensible" for it to beint
, since bothMaxDays
(10,675,199
) andMaxHours
(256,204,778
) are withinint.MaxValue
. That is also why the signatures areFromDays(int days, int hours, long minutes, long milliseconds, long microseconds)
. So other values, likeMinutesPerDay
(1440
),MinutesPerHour
(60
), or even the existingMillisecondsPerTick
(10,000
) are all expected to be used in contexts wherelong
is the target type.When considering TimeSpan, which is where these constants are defined, hours and days are int, all other units are long.
Background and motivation
In the
TimeSpan
class there are a fewpublic const
values that are generally applicable that are usefully exposed.There are also a bunch more that are
internal const
but would be generally useful for other code and are not more implementation driven than the already exposed const values.These values should be exposed publicly on the TimeSpan class.
Note: NOT suggesting we expose the truly
internal const
values that are related toMinTicks
andMaxTicks
. They could be included but are just not as naturally useful elsewhere.API Proposal
API Usage
Alternative Designs
N/A
Risks
Since these are compile-time constant values, there would be no runtime cost in either memory or execution overhead. Additionally they would centralize basic real-world facts to one logical location (TimeSpan).
The text was updated successfully, but these errors were encountered: