[c#] DateTime 객체 반올림

차트 응용 프로그램의 날짜 / 시간을 가장 가까운 간격으로 반올림하고 싶습니다. 모든 수준의 정확성에 대해 반올림을 수행 할 수 있도록 다음과 같은 확장 메서드 서명을 원합니다.

static DateTime Round(this DateTime date, TimeSpan span);

아이디어는 내가 10 분의 시간 범위를 지나면 가장 가까운 10 분 간격으로 반올림된다는 것입니다. 나는 구현에 대해 내 머리를 이해할 수 없으며 당신 중 한 명이 전에 비슷한 것을 작성하거나 사용하기를 바라고 있습니다.

나는 바닥, 천장 또는 가장 가까운 구현이 괜찮다고 생각합니다.

어떤 아이디어?

편집 : @tvanfosson & @ShuggyCoUk 덕분에 구현은 다음과 같습니다.

public static class DateExtensions {
    public static DateTime Round(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }
    public static DateTime Floor(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks / span.Ticks);
        return new DateTime(ticks * span.Ticks);
    }
    public static DateTime Ceil(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks + span.Ticks - 1) / span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }
}

그리고 이렇게 불립니다 :

DateTime nearestHour = DateTime.Now.Round(new TimeSpan(1,0,0));
DateTime minuteCeiling = DateTime.Now.Ceil(new TimeSpan(0,1,0));
DateTime weekFloor = DateTime.Now.Floor(new TimeSpan(7,0,0,0));
...

건배!



답변

바닥

long ticks = date.Ticks / span.Ticks;

return new DateTime( ticks * span.Ticks );

라운드 (중간 지점에서 위로)

long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;

return new DateTime( ticks * span.Ticks );

천장

long ticks = (date.Ticks + span.Ticks - 1)/ span.Ticks;

return new DateTime( ticks * span.Ticks );


답변

이렇게하면 주어진 간격으로 반올림 할 수 있습니다. 또한 눈금을 나누고 곱하는 것보다 약간 빠릅니다.

public static class DateTimeExtensions
{
  public static DateTime Floor(this DateTime dateTime, TimeSpan interval)
  {
    return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks));
  }

  public static DateTime Ceiling(this DateTime dateTime, TimeSpan interval)
  {
    var overflow = dateTime.Ticks % interval.Ticks;

    return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow);
  }

  public static DateTime Round(this DateTime dateTime, TimeSpan interval)
  {
    var halfIntervalTicks = (interval.Ticks + 1) >> 1;

    return dateTime.AddTicks(halfIntervalTicks - ((dateTime.Ticks + halfIntervalTicks) % interval.Ticks));
  }
}


답변

반올림을 다음과 같은 경우에도 명확해야합니다.

  1. 간격의 시작, 끝 또는 중간까지
    • 시작이 가장 쉽고 자주 예상되지만 초기 사양에서 명확해야합니다.
  2. 경계 케이스를 반올림하는 방법.
    • 일반적으로 끝이 아닌 중간으로 반올림하는 경우에만 문제가됩니다.
    • 중간으로 반올림하는 것은 편견이없는 답변을 시도 하는 것이므로 편향에서 진정으로 해방 되려면 Bankers Rounding 기술적으로 반올림 과 같은 것을 사용해야합니다 .

실제로 첫 번째 지점에만 관심이있을 가능성이 높지만 이러한 ‘간단한’질문에서 결과 동작은 실제 세계에서 사용할 때 광범위한 결과를 초래할 수 있습니다 (종종 0에 인접한 간격에서)

tvanfosson의 솔루션은 1에 나열된 모든 경우를 다룹니다. 중간 지점 예는 위쪽으로 치우쳐 있습니다. 이것이 시간 관련 반올림에서 문제가 될지는 의심 스럽다.


답변

Ticks를 사용하여 나누고 값을 바닥 / 천장 / 반올림 한 다음 다시 곱하십시오.


답변

시간을 상한값으로 반올림하려는 경우

Console.WriteLine(DateTime.Now.ToString("M/d/yyyy hh:00:00"));


답변