2012-04-11 3 views
8

Например:Есть ли простая функция округления DateTime до 30 минут, в C#?

2011-08-11 16:59 становится 2011-08-11 16:30

+1

В библиотеках базового класса такой функции нет. –

+0

Нет такой функции Вы можете обратиться к: [http://stackoverflow.com/questions/7029353/c-sharp-round-up-time-to-nearest-x-minutes][1] [1]: http://stackoverflow.com/questions/7029353/c-sharp-round-up-time-to-nearest-x-minutes – Thakur

+0

http://stackoverflow.com/questions/ 1393696/c-sharp-rounding-datetime-objects – Chris

ответ

16

Я хотел бы сказать что-то вроде этого

var time = DateTime.Now; 
var rounded = time.AddMinutes(
     time.Minute>30 ? -(time.Minute-30) : -time.Minute) 

И вы можете даже сделать свой собственный расширение

public static class TimeHelper { 
    public static DateTime RoundDown (this DateTime time) 
    { 
     return time.AddMinutes(
     time.Minute>30 ? -(time.Minute-30) : -time.Minute); 
    } 
} 

EDIT

Эта функция вырезает также секунды/миллисекунды, если необходимо. Спасибо за подсказку.

public static DateTime RoundDown(this DateTime time) 
{ 
    return time.Subtract(
     new TimeSpan(0, 0, time.Minute > 30 ? (time.Minute - 30) : time.Minute, 
      time.Second, time.Millisecond)); 
} 
+2

+1 Решение, которое не выдает значение DateTime.Kind :) –

+0

Как написано, 'Minutes' не компилируется - в типе 'DateTime' нет свойства Minutes. Переход на «Минуту» компилируется, но поскольку свойство «Minute' является« int », секунды будут оставаться в округленном результате, а не усекаться до отметки всей минуты, как желает OP. – devgeezer

+0

Thx для искателя подсказок. Я обновил свой ответ. – BitKFu

2
DateTime newDateTime = new DateTime(oldDateTime.Year, oldDateTime.Month, oldDateTime.Day 
    ,oldDateTime.Hour, (oldDateTime.Minute/30) * 30, 0); 
0

Там нет такой функции доступны

Вы можете обратиться к: How can I round up the time to the nearest X minutes?

При необходимости вы можете создать себе

DateTime RoundUp(DateTime dt, TimeSpan d) 
{ 
    return new DateTime(((dt.Ticks - d.Ticks + 1)/d.Ticks) * d.Ticks + d.Ticks); 
} 

например:

var dt1 = RoundUp(DateTime.Parse("2011-08-11 16:59"), TimeSpan.FromMinutes(30)); 
// dt1 == {11/08/2011 16:30:00} 
+0

, но его ближайшие 30 минут - '16: 30' – V4Vendetta

+0

@ V4Vendetta мой плохой. теперь это исправлено. – Thakur

17
DateTime RoundDown(DateTime dt, TimeSpan d) 
{ 
    return new DateTime((dt.Ticks/d.Ticks) * d.Ticks); 
} 

Пример:

var dt1 = RoundDown(DateTime.Parse("2011-08-11 16:59"), TimeSpan.FromMinutes(30)); 
// dt1 == {11/08/2011 16:30:00} 

var dt2 = RoundDown(DateTime.Parse("2011-08-11 17:00"), TimeSpan.FromMinutes(30)); 
// dt2 == {11/08/2011 17:00:00} 

var dt3 = RoundDown(DateTime.Parse("2011-08-11 17:01"), TimeSpan.FromMinutes(30)); 
// dt3 == {11/08/2011 17:00:00} 
+0

Спасибо! Вы видите проблемы с округлением? Я пытаюсь RoundDown до ближайшей минуты, и я случайно получаю два разных ответа за один и тот же интервал. – Legend

0

Эксплуатируя некоторые математические

var input = DateTime.Now; // or however you get DateTime 
var rounded = input.AddMinutes(-input.TimeOfDay.TotalMinutes % 30d); 

Обратите внимание, что TimeOfDay является TimeSpan и его свойство TotalMinutes является double и что оператор-функции модуля на парном как следует:

47,51% 30d == 17,51

16,2% 30d == 16,2

768,7% 30d == 18,7

Вы можете изменить 30d в любое значение, как отличное от нуля. Например, до 15 раундов до 15-минутных интервалов. Изменение с 30d на -30d не изменило результаты тестов, которые я запускал.

Вы можете создать скругления метод расширения (при условии, этот метод округления для всех значений DateTime):

public static class DateTimeExtensions 
{ 
    public static DateTime Round(this DateTime self, double minutesInInterval) 
    { 
     if (minutesInInterval == 0d) throw new ArgumentOutOfRangeException("minutesInInterval"); 
     return self.AddMinutes(-self.TimeOfDay.TotalMinutes % minutesInInterval); 
    } 
} 
3

Более общее решение округление до ближайшего промежутка времени:


public static DateTime RoundUp(this DateTime dt, TimeSpan d) 
{ 
    var delta = (d.Ticks - (dt.Ticks % d.Ticks)) % d.Ticks; 
    return new DateTime(dt.Ticks + delta); 
} 

public static DateTime RoundDown(this DateTime dt, TimeSpan d) 
{ 
    var delta = dt.Ticks % d.Ticks; 
    return new DateTime(dt.Ticks - delta); 
} 

public static DateTime RoundToNearest(this DateTime dt, TimeSpan d) 
{ 
    var delta = dt.Ticks % d.Ticks; 
    bool roundUp = delta > d.Ticks/2; 

    return roundUp ? dt.RoundUp(d) : dt.RoundDown(d); 
}

Было бы используется таким образом:

var date = new DateTime(2010, 02, 05, 10, 35, 25, 450); // 2010/02/05 10:35:25 
var rounded = date.RoundToNearest(TimeSpan.FromMinutes(30)); // 2010/02/05 10:30:00

Подробнее в this response.

0

Вот как я справился с этим. Ниже приведен базовый метод и перегрузка до округления до ближайших 30 минут:

public static DateTime RoundMinutes(this DateTime value) 
{ 
    return RoundMinutes(value, 30); 
} 

public static DateTime RoundMinutes(this DateTime value, int roundMinutes) 
{ 
    DateTime result = new DateTime(value.Ticks); 

    int minutes = value.Minute; 
    int hour = value.Hour; 
    int minuteMod = minutes % roundMinutes; 

    if (minuteMod <= (roundMinutes/2)) 
    { 
     result = result.AddMinutes(-minuteMod); 
    } 
    else 
    { 
     result = result.AddMinutes(roundMinutes - minuteMod); 
    } 

    return result; 
} 
Смежные вопросы