programing

DateTime 객체 반올림

nasanasas 2020. 8. 19. 08:17
반응형

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. be to the start, end or middle of the interval
    • start is the easiest and often the expected but you should be clear in your initial spec.
  2. How you want boundary cases to round.
    • normally only an issue if you are rounding to the middle rather than the end.
    • Since rounding to the middle is an attempt at a bias free answer you need to use something like Bankers Rounding technically round half even to be truly free from bias.

It is quite likely that you really only care about the first point but in these 'simple' questions the resulting behaviour can have far reaching consequences as you use it in the real world (often at the intervals adjacent to zero)

tvanfosson's solution's cover all the cases listed in 1. The midpoint example is biased upwards. It is doubtful that this would be a problem in time related rounding.


Just use the Ticks, using that to divide, floor/ceil/round the value, and multiply it back.


If you just want to round up the Hour to Ceiling Value

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

참고URL : https://stackoverflow.com/questions/1393696/rounding-datetime-objects

반응형