Create a gist now

Instantly share code, notes, and snippets.

.NETのDateTimeを正しく(タイムゾーンが異なるインスタンス同士でも絶対時刻の前後で)比較するメソッド
using System;
namespace Common
{
public static class DateTimeUtil
{
/// <summary>
/// 二つの時刻値の大きい方を返します。
/// ただし、タイムゾーン設定が異なる場合、Utc>Local>Unspecifiedの優先順位で高い方にそろえます。
/// LocalをUtcにそろえるときは時刻換算が発生します。
/// UnspecifiedをLocalやUtcにそろえるときは、最初からLocalやUtcだったものと仮定し時刻換算が発生しません。
/// </summary>
public static DateTime Max(DateTime a, DateTime b)
{
return MatchDateTimes(a, b, Math.Max);
}
/// <summary>
/// 二つの時刻値の小さい方を返します。
/// ただし、タイムゾーン設定が異なる場合、Utc>Local>Unspecifiedの優先順位で高い方にそろえます。
/// LocalをUtcにそろえるときは時刻換算が発生します。
/// UnspecifiedをLocalやUtcにそろえるときは、最初からLocalやUtcだったものと仮定し時刻換算が発生しません。
/// </summary>
public static DateTime Min(DateTime a, DateTime b)
{
return MatchDateTimes(a, b, Math.Min);
}
/// <summary>
/// 二つの時刻値を同じ種類にそろえて、指定のデリゲートに渡します。
/// タイムゾーン設定が異なる場合、Utc>Local>Unspecifiedの優先順位で高い方にそろえます。
/// LocalをUtcにそろえるときは時刻換算が発生します。
/// UnspecifiedをLocalやUtcにそろえるときは、最初からLocalやUtcだったものと仮定し時刻換算が発生しません。
/// </summary>
private static DateTime MatchDateTimes(DateTime a, DateTime b, Func<long, long, long> process)
{
switch (a.Kind)
{
case DateTimeKind.Local:
if (b.Kind == DateTimeKind.Utc)
return new DateTime(process(a.ToUniversalTime().Ticks, b.Ticks), DateTimeKind.Utc);
else
return new DateTime(process(a.Ticks, b.Ticks), DateTimeKind.Local);
case DateTimeKind.Utc:
if (b.Kind == DateTimeKind.Local)
return new DateTime(process(a.Ticks, b.ToUniversalTime().Ticks), DateTimeKind.Utc);
else
return new DateTime(process(a.Ticks, b.Ticks), DateTimeKind.Utc);
}
return new DateTime(process(a.Ticks, b.Ticks), b.Kind);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment