using System.Text; namespace System { /// /// Provides extension methods for date and time manipulation. /// public static class DateTimeExtensions { #region Kind /// /// Specifies the as UTC. /// /// The instance. /// A with correct . public static DateTime AsUtc(this DateTime dt) { return dt.Kind switch { DateTimeKind.Local => dt.ToUniversalTime(), DateTimeKind.Utc => dt, _ => DateTime.SpecifyKind(dt, DateTimeKind.Utc), }; } /// /// Specifies the as local time. /// /// The instance. /// A with correct . public static DateTime AsLocal(this DateTime dt) { return dt.Kind switch { DateTimeKind.Local => dt, DateTimeKind.Utc => dt.ToLocalTime(), _ => DateTime.SpecifyKind(dt, DateTimeKind.Local), }; } #endregion Kind /// /// Aligns the to the clock. /// /// The timespan to align. /// A specific offset to the timespan. /// The timespan until the aligned time. public static TimeSpan GetAlignedInterval(this TimeSpan timeSpan, TimeSpan offset = default) { var now = DateTime.UtcNow; var nextTime = new DateTime(now.Ticks / timeSpan.Ticks * timeSpan.Ticks) + offset; if (nextTime <= now) nextTime += timeSpan; return nextTime - now; } /// /// Prints the timespan as shortended string. /// /// The timespan /// A value indicating whether to show milliseconds. /// The timespan as string. public static string ToShortString(this TimeSpan timeSpan, bool withMilliseconds = false) { var sb = new StringBuilder(); if (timeSpan.TotalDays >= 1) sb.Append(timeSpan.Days).Append("d "); if (timeSpan.TotalHours >= 1) sb.Append(timeSpan.Hours).Append("h "); if (timeSpan.TotalMinutes >= 1) sb.Append(timeSpan.Minutes).Append("m "); sb.Append(timeSpan.Seconds).Append("s "); if (withMilliseconds) sb.Append(timeSpan.Milliseconds).Append("ms"); return sb.ToString().Trim(); } #region Round DateTime /// /// Rounds the to full seconds. /// /// The time value to round. /// public static DateTime RoundToSecond(this DateTime dt) { return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerSecond), dt.Kind); } /// /// Rounds the to full minutes. /// /// The time value to round. /// public static DateTime RoundToMinute(this DateTime dt) { return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerMinute), dt.Kind); } /// /// Rounds the to full hours. /// /// The time value to round. /// public static DateTime RoundToHour(this DateTime dt) { return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerHour), dt.Kind); } /// /// Rounds the to full days. /// /// The time value to round. /// public static DateTime RoundToDay(this DateTime dt) { return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerDay), dt.Kind); } #endregion Round DateTime #region Round TimeSpan /// /// Rounds the to full seconds. /// /// The time value to round. /// public static TimeSpan RoundToSecond(this TimeSpan timeSpan) { return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond)); } /// /// Rounds the to full minutes. /// /// The time value to round. /// public static TimeSpan RoundToMinute(this TimeSpan timeSpan) { return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute)); } /// /// Rounds the to full hours. /// /// The time value to round. /// public static TimeSpan RoundToHour(this TimeSpan timeSpan) { return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour)); } /// /// Rounds the to full days. /// /// The time value to round. /// public static TimeSpan RoundToDay(this TimeSpan timeSpan) { return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerDay)); } #endregion Round TimeSpan private static long RoundTicks(long ticks, long value) { return (ticks + value / 2) / value * value; } } }