/// <summary>
/// Converts Timespec to DateTime.
/// Timespec needs to be of type GPRClockType.Realtime and needs to represent a legal value.
/// DateTime has lower resolution (100ns), so rounding can occurs.
/// Value are always rounded up to the nearest DateTime value in the future.
///
/// For Timespec.InfFuture or if timespec is after the largest representable DateTime, DateTime.MaxValue is returned.
/// For Timespec.InfPast or if timespec is before the lowest representable DateTime, DateTime.MinValue is returned.
///
/// Unless DateTime.MaxValue or DateTime.MinValue is returned, the resulting DateTime is always in UTC
/// (DateTimeKind.Utc)
/// </summary>
public DateTime ToDateTime()
{
Preconditions.CheckState(tv_nsec >= 0 && tv_nsec < NanosPerSecond);
Preconditions.CheckState(clock_type == GPRClockType.Realtime);
// fast path for InfFuture
if (this.Equals(InfFuture))
{
return(DateTime.MaxValue);
}
// fast path for InfPast
if (this.Equals(InfPast))
{
return(DateTime.MinValue);
}
try
{
// convert nanos to ticks, round up to the nearest tick
long ticksFromNanos = tv_nsec / NanosPerTick + ((tv_nsec % NanosPerTick != 0) ? 1 : 0);
long ticksTotal = checked (tv_sec.ToInt64() * TicksPerSecond + ticksFromNanos);
return(UnixEpoch.AddTicks(ticksTotal));
}
catch (OverflowException)
{
// ticks out of long range
return(tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue);
}
catch (ArgumentOutOfRangeException)
{
// resulting date time would be larger than MaxValue
return(tv_sec.ToInt64() > 0 ? DateTime.MaxValue : DateTime.MinValue);
}
}