Подтвердить что ты не робот

DateTime Round Up и Down

Я искал подходящий механизм округления, но ничего, что я нахожу, кажется, именно то, что мне нужно.

Мне нужно округлить и округлить отдельно, и мне также нужно учитывать случай, когда он уже закруглен.

Мне нужно следующее округление

5:00 -> RoundDown() -> 5:00
5:04 -> RoundDown() -> 5:00
5:09 -> RoundDown() -> 5:00
5:10 -> RoundDown() -> 5:10

4:00 -> RoundUp() -> 4:00
4:50 -> RoundUp() -> 4:50
4:51 -> RoundUp() -> 5:00
4:56 -> RoundUp() -> 5:00 

В принципе, я нуждаюсь в нем RoundUp() или RoundDown() до ближайших 10 минут явно, но он также должен оставить время нетронутым, если оно уже в течение 10 минут. Также я хотел бы усекать любые секунды, чтобы они не влияли на процедуру округления.

4:50:45 → 4:50:00 → RoundUp() → 4:50

Есть ли у кого-нибудь удобный код для этого.

Я нашел этот код где-нибудь, но он округляет 5:00 → RoundUp() → 5:10, а не оставляет его нетронутым, потому что он уже кратен 10 и не нуждается в округлении. Также я не уверен, как секунд это повлияет на него.

public static DateTime RoundDateTime(this DateTime dt, int minutes, RoundingDirection direction)
{
    TimeSpan t;
    switch (direction)
    {
        case RoundingDirection.Up:
            t = (dt.Subtract(DateTime.MinValue)).Add(new TimeSpan(0, minutes, 0)); break;
        case RoundingDirection.Down:
            t = (dt.Subtract(DateTime.MinValue)); break;
        default:
            t = (dt.Subtract(DateTime.MinValue)).Add(new TimeSpan(0, minutes / 2, 0)); break;
    }
    return DateTime.MinValue.Add(new TimeSpan(0,
           (((int)t.TotalMinutes) / minutes) * minutes, 0));
}

Надеюсь, кто-то может отредактировать этот метод, чтобы он работал у меня. Благодаря

4b9b3361

Ответ 1

Как насчет:

case RoundingDirection.Up:
    t = dt.AddMinutes((60 - dt.Minute) % 10);
case RoundingDirection.Down:
    t = dt.AddMinutes(-dt.Minute % 10);

Демо: http://ideone.com/AlB7Q

Ответ 2

Это позволит вам округлить в соответствии с любым интервалом.

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));
  }
}

Чтобы порезать секунды, я просто вычел бы секунды и миллисекунды из даты и времени перед отправкой их в функции округления.

Ответ 3

Эта функция будет округлить вверх или вниз до ближайшего интервала (минут).

    private static DateTime NormalizeReadingInterval(DateTime originalTime, int interval)
    {
        if (originalTime.Minute % interval == 0) return originalTime;
        var epochTime = new DateTime(1900, 1, 1);
        var minutes = (originalTime - epochTime).TotalMinutes;
        var numIntervals = minutes / interval;
        var roundedNumIntervals = Math.Round(numIntervals, 0);
        return epochTime.AddMinutes(roundedNumIntervals * interval);
    }

Ответ 4

Вот быстрый способ обрезать (округлить)

var now = DateTime.Now;
var nowTicks = now.Ticks;

//removing the nanoseconds, miliseconds, and seconds from the nowTicks
var lastMinute = new DateTime(nowTicks - (nowTicks % (1000*1000*10*60)));