Вырезать/округлить DateTime до целого, т.е. Hour/Day?
Есть ли какой-либо математический способ сократить DateTime до определенного часа, дня или около того? Совпадает с округлением десятичного числа до int.
Period.Day
Если первоначальное значение было 2011-01-01 13:00:00
, оно заканчивается в 2011-01-01 00:00:00
если Period.Hour
Если первоначальное значение было 2011-03-11 13:32:00
, оно заканчивается в 2011-03-11 13:00:00
Я думаю о чем-то вроде ниже. Это, конечно, отлично работает, но range
-array в любом случае повторяется. Лучше, если бы я мог рассчитывать непосредственно на этой итерации, а не на нее. Но someType не может быть помещен в эту итерацию (это зависит от someType).
if (someType == Period.Day)
range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day,0,0,0));
if (someType == Period.Hour)
range.ForEach(d => d.time = new DateTime(d.time.Year, d.time.Month, d.time.Day, d.time.Hour, 0, 0));
Ответы
Ответ 1
Округление до дня эквивалентно time.Date
, округление до ближайшего (вверх по середине) просто ( time + 12hours).Date
.
Для округления до полного часа я не могу придумать код, который лучше читать, чем ваш. Для округления до ближайшего часа вы можете применить свой код к time + 30mins
.
Вероятно, существует более быстрый метод округления до ближайшего часа:
const Int64 HourInTicks=...;
Int64 timeInTicks=time.Ticks;
Int64 trucatedToHour=timeInTicks-timeInTicks%HourInTicks;
Но я бы избежал этого, если вам действительно не нужна производительность, что маловероятно.
(Мой раунд до ближайшего может иметь проблемы в дни, когда местное смещение времени изменяется, если вы используете локальное время)
Ответ 2
Для округления до конца вы можете использовать свойство DateTime.Date.
Чтобы округлить до часа, я боюсь, вам придется либо использовать то, что вы сделали в своем примере, или что-то вроде:
d.Date.AddHours(d.Hour)
Ответ 3
Я сделаю следующее:
private static readonly DateTime Epoch = new DateTime(1970, 1, 1);
public static DateTime Round(this DateTime d, Period p)
{
var ts = d - Epoch;
if (p == Period.Hour)
{
var hours = (long)ts.TotalHours;
return Epoch.AddHours(hours);
}
else if (p == Period.Days)
{
var days = (long)ts.TotalDays;
return Epoch.AddDays(days);
}
// ...
}
Ответ 4
Я считаю, что следующий код С# будет округлять значение DateTime до ближайшей минуты, и я думаю, что будет легко обобщить его на раунд для других единиц.
//round to nearest minute; add 30 seconds for rounding to nearest minute
effectiveDateTime = effectiveDateTime.AddSeconds(30);
TimeSpan timeComponent = effectiveDateTime.TimeOfDay;
effectiveDateTime = effectiveDateTime.Date;
effectiveDateTime = effectiveDateTime.AddHours(timeComponent.Hours).
AddMinutes(timeComponent.Minutes);
Ответ 5
Не уверен, что этот подход эффективен, но выглядит довольно неплохо, используя строковый формат (в этом случае сокращение до нескольких часов):
var date = DateTime.UtcNow;
var cutDownDate = Convert.ToDateTime(date.ToString("yyyy-MM-dd hh"));
Ответ 6
Ответ. Есть ли лучший способ в С# округлить DateTime до ближайших 5 секунд? содержит отличный общий подход округления DateTime
.
Изменение: этот ответ был до обновленного заголовка вопроса и является алгоритмом округления до ближайшего не округления.