-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.DateTime
Milestone
Description
Currently, the value of a single Tick in .NET is 100ns, however there is no API surface for accessing microseconds or nanoseconds other than using Ticks to manually calculate these numbers. In order to allow for working with these higher precision times, I am proposing the following new APIs:
Approved API
namespace System {
public struct DateTime {
/// <exception cref="ArgumentOutOfRangeException">When microsecond is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond);
/// <exception cref="ArgumentOutOfRangeException">When microsecond is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.DateTimeKind kind);
/// <exception cref="ArgumentOutOfRangeException">When microsecond is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.Globalization.Calendar calendar);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
/// <exception cref="ArgumentOutOfRangeException">The resulting DateTime is less than DateTime.MinValue or greater than DateTime.MaxValue.</exception>
public DateTime AddMicroseconds(double value);
}
public struct DateTimeOffset {
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.TimeSpan offset);
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.TimeSpan offset, System.Globalization.Calendar calendar);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
/// <exception cref="ArgumentOutOfRangeException">The resulting DateTimeOffset is less than DateTimeOffset.MinValue or greater than DateTimeOffset.MaxValue.</exception>
public DateTimeOffset AddMicroseconds(double value);
}
public struct TimeSpan {
public const long TicksPerMicrosecond = 10L;
public const long NanosecondsPerTick = 100L;
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds, int microseconds);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microseconds { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanoseconds { get; }
/// <returns>The total number of microseconds represented by this instance.</returns>
public double TotalMicroseconds { get; }
/// <returns>The total number of nanoseconds represented by this instance.</returns>
public double TotalNanoseconds { get; }
/// <exception cref="OverflowException">When value is less than TimeSpan.MinValue or greater than TimeSpan.MaxValue.</exception>
public static TimeSpan FromMicroseconds(double microseconds);
}
public struct TimeOnly {
/// <param name="microsecond">The microsecond (0 through 999).</param>
/// <exception cref="ArgumentOutOfRangeException">When microsecond is not between 0 and 999.</exception>
public TimeOnly(int day, int hour, int minute, int second, int millisecond, int microsecond);
/// <returns>The microsecond component of the time represented by this instant, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanosecond component of the time represented by this instant, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
}
}Original API Proposal
namespace System {
public struct DateTime {
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds);
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds, System.DateTimeKind kind);
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds, System.Globalization.Calendar calendar);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
/// <exception cref="ArgumentOutOfRangeException">The resulting DateTime is less than DateTime.MinValue or greater than DateTime.MaxValue.</exception>
public DateTime AddMicroseconds(int microseconds);
}
public struct DateTimeOffset {
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds, System.TimeSpan offset);
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds, System.TimeSpan offset, System.Globalization.Calendar calendar);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
/// <exception cref="ArgumentOutOfRangeException">The resulting DateTimeOffset is less than DateTimeOffset.MinValue or greater than DateTimeOffset.MaxValue.</exception>
public DateTimeOffset AddMicroseconds(int microseconds);
}
public struct TimeSpan {
public const long TicksPerMicrosecond = 10L;
public const double TicksPerNanosecond = 0.01D;
/// <exception cref="ArgumentOutOfRangeException">When microseconds is not between 0 and 999.</exception>
public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds, int microseconds);
/// <returns>The microseconds component, expressed as a value between 0 and 999.</returns>
public int Microseconds { get; }
/// <returns>The nanoseconds component, expressed as a value between 0 and 900.</returns>
public int Nanoseconds { get; }
/// <returns>The total number of microseconds represented by this instance.</returns>
public double TotalMicroseconds { get; }
/// <returns>The total number of nanoseconds represented by this instance.</returns>
/// <exception cref="OverflowException">When value starts to approach TimeSpan.MinValue or TimeSpan.MaxValue.</exception>
public double TotalNanoseconds { get; }
/// <exception cref="OverflowException">When value is less than TimeSpan.MinValue or greater than TimeSpan.MaxValue.</exception>
public static TimeSpan FromMicroseconds(double value);
}
public struct TimeOnly {
/// <param name="microsecond">The microsecond (0 through 999).</param>
/// <exception cref="ArgumentOutOfRangeException">When microsecond is not between 0 and 999.</exception>
public TimeOnly(int day, int hour, int minute, int second, int millisecond, int microsecond);
/// <returns>The microsecond component of the time represented by this instant, expressed as a value between 0 and 999.</returns>
public int Microsecond { get; }
/// <returns>The nanosecond component of the time represented by this instant, expressed as a value between 0 and 900.</returns>
public int Nanosecond { get; }
}
}Example Usage
public class Samples
{
public void DateTimeSamples()
{
new DateTime(0001, 01, 01, 00, 00, 00, 00, 999).Ticks; // 9990
DateTime.Parse("0001-01-01 00:00:00.0009990").Microsecond; // 999
DateTime.Parse("0001-01-01 00:00:00.0000009").Nanosecond; // 900
DateTime.Zero.AddMicroseconds(999).Ticks; // 9990
}
public void DateTimeOffsetSamples()
{
new DateTimeOffset(0001, 01, 01, 00, 00, 00, 00, 999, TimeSpan.FromHours(-7)).Ticks; // 9990
DateTimeOffset.Parse("0001-01-01 00:00:00.0009990 -7").Microsecond; // 999
DateTimeOffset.Parse("0001-01-01 00:00:00.0000009 -7").Nanosecond; // 900
new DateTimeOffset().AddMicroseconds(999).Ticks; // 9990
}
public void TimeSpanSamples()
{
new TimeSpan(999 * TimeSpan.TicksPerMicrosecond).Ticks; // 9990
new TimeSpan((long)(900 * TimeSpan.TicksPerNanosecond)).Ticks; // 9
new TimeSpan(0001, 01, 01, 00, 00, 00, 00, 999).Ticks; // 9990
TimeSpan.Parse("0001-01-01 00:00:00.0009990").Microsecond; // 999
TimeSpan.Parse("0001-01-01 00:00:00.0000009").Nanosecond; // 900
TimeSpan.Zero.AddMicroseconds(999).Ticks; // 9990
}
}Notes
TimeSpan.TotalMicrosecondsandTimeSpan.TotalNanosecondsreturn double still since that is what the otherTotalproperties return. This could be long but I kept it as double for consistency.TimeSpan.FromMicrosecondstakes a double to keep the API consistent with the otherFrommethods.
shef, HalidCisse, dylanmckendry, wqnvlz, hoffmann-stefan and 3 moreiamcarbon
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.DateTime