183 lines
5.4 KiB
C#
183 lines
5.4 KiB
C#
using System.Text;
|
|
|
|
namespace System
|
|
{
|
|
/// <summary>
|
|
/// Provides extension methods for date and time manipulation.
|
|
/// </summary>
|
|
public static class DateTimeExtensions
|
|
{
|
|
#region Kind
|
|
|
|
/// <summary>
|
|
/// Specifies the <see cref="DateTime.Kind"/> as UTC.
|
|
/// </summary>
|
|
/// <param name="dt">The <see cref="DateTime"/> instance.</param>
|
|
/// <returns>A <see cref="DateTime"/> with correct <see cref="DateTime.Kind"/>.</returns>
|
|
public static DateTime AsUtc(this DateTime dt)
|
|
{
|
|
return dt.Kind switch
|
|
{
|
|
DateTimeKind.Local => dt.ToUniversalTime(),
|
|
DateTimeKind.Utc => dt,
|
|
_ => DateTime.SpecifyKind(dt, DateTimeKind.Utc),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Specifies the <see cref="DateTime.Kind"/> as local time.
|
|
/// </summary>
|
|
/// <param name="dt">The <see cref="DateTime"/> instance.</param>
|
|
/// <returns>A <see cref="DateTime"/> with correct <see cref="DateTime.Kind"/>.</returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Aligns the <see cref="TimeSpan"/> to the clock.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The timespan to align.</param>
|
|
/// <param name="offset">A specific offset to the timespan.</param>
|
|
/// <returns>The timespan until the aligned time.</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prints the timespan as shortended string.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The timespan</param>
|
|
/// <param name="withMilliseconds">A value indicating whether to show milliseconds.</param>
|
|
/// <returns>The timespan as string.</returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="DateTime"/> to full seconds.
|
|
/// </summary>
|
|
/// <param name="dt">The time value to round.</param>
|
|
/// <returns></returns>
|
|
|
|
public static DateTime RoundToSecond(this DateTime dt)
|
|
{
|
|
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerSecond), dt.Kind);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="DateTime"/> to full minutes.
|
|
/// </summary>
|
|
/// <param name="dt">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static DateTime RoundToMinute(this DateTime dt)
|
|
{
|
|
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerMinute), dt.Kind);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="DateTime"/> to full hours.
|
|
/// </summary>
|
|
/// <param name="dt">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static DateTime RoundToHour(this DateTime dt)
|
|
{
|
|
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerHour), dt.Kind);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="DateTime"/> to full days.
|
|
/// </summary>
|
|
/// <param name="dt">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static DateTime RoundToDay(this DateTime dt)
|
|
{
|
|
return new DateTime(RoundTicks(dt.Ticks, TimeSpan.TicksPerDay), dt.Kind);
|
|
}
|
|
|
|
#endregion Round DateTime
|
|
|
|
#region Round TimeSpan
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="TimeSpan"/> to full seconds.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static TimeSpan RoundToSecond(this TimeSpan timeSpan)
|
|
{
|
|
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerSecond));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="TimeSpan"/> to full minutes.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static TimeSpan RoundToMinute(this TimeSpan timeSpan)
|
|
{
|
|
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerMinute));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="TimeSpan"/> to full hours.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The time value to round.</param>
|
|
/// <returns></returns>
|
|
public static TimeSpan RoundToHour(this TimeSpan timeSpan)
|
|
{
|
|
return new TimeSpan(RoundTicks(timeSpan.Ticks, TimeSpan.TicksPerHour));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rounds the <see cref="TimeSpan"/> to full days.
|
|
/// </summary>
|
|
/// <param name="timeSpan">The time value to round.</param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
}
|
|
}
|