我需要根据DateTime变量中的分钟来舍入小时数。条件是:如果分钟小于30,则必须将分钟设置为零并且不更改为小时,否则如果分钟> = 30,则必须将小时设置为小时+ 1并且将分钟再次设置为零。秒被忽略。
例如:
11/08/2008 04:30:49
应成为11/08/2008 05:00:00
11/08/2008 04:29:49
应成为11/08/2008 04:00:00
我编写的代码完全正常,但只是想知道一个更好的方法,如果可以编写,也会欣赏替代方法。
string date1 = "11/08/2008 04:30:49";
DateTime startTime;
DateTime.TryParseExact(date1, "MM/dd/yyyy HH:mm:ss", null,
System.Globalization.DateTimeStyles.None, out startTime);
if (Convert.ToInt32((startTime.Minute.ToString())) > 29)
{
startTime = DateTime.Parse(string.Format("{0}/{1}/{2} {3}:{4}:{5}",
startTime.Month.ToString(), startTime.Day.ToString(),
startTime.Year.ToString(), startTime.Hour.ToString(), "00", "00"));
startTime = startTime.Add(TimeSpan.Parse("01:00:00"));
Console.WriteLine("startTime is :: {0}",
startTime.ToString("MM/dd/yyyy HH:mm:ss"));
}
else
{
startTime = DateTime.Parse(string.Format("{0}/{1}/{2} {3}:{4}:{5}",
startTime.Month.ToString(),
startTime.Day.ToString(), startTime.Year.ToString(),
startTime.Hour.ToString(), "00", "00"));
Console.WriteLine("startTime is :: {0}",
startTime.ToString("MM/dd/yyyy HH:mm:ss"));
}
答案 0 :(得分:29)
作为替代方案:
public static DateTime Round( DateTime dateTime )
{
var updated = dateTime.AddMinutes( 30 );
return new DateTime( updated.Year, updated.Month, updated.Day,
updated.Hour, 0, 0, dateTime.Kind );
}
答案 1 :(得分:22)
如果速度是个问题,以下应该是最快的方法:
static DateTime RoundToHour(DateTime dt){
long ticks = dt.Ticks + 18000000000;
return new DateTime(ticks - ticks % 36000000000, dt.Kind);
}
这也是一种非常直接且简单的方法。
为了解释,DateTime结构实际上没有存储年,月,日,小时,分钟等的字段。它存储一个long
值,即自某个值以来的“滴答”数时代(公元1月1日)。刻度是100纳秒,或者是10,000,000秒。
每次使用任何日期/时间属性时,它都会除以适当的常量。
所以在这里,我们添加一个等于30分钟的常数(30 * 60 * 1e7 = 18000000000个刻度),然后在除以等于1小时的常数(60 * 60 * 1e7 = 36000000000个刻度)后减去余数。 / p>
答案 2 :(得分:6)
怎么样:
public static DateTime RoundToHours(DateTime input)
{
DateTime dt = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
if (input.Minute > 29)
return dt.AddHours(1);
else
return dt;
}
无需转换为字符串并再次返回!
编辑:
如果小时为23,则在构造函数中使用input.Hour+1
将失败。.AddHours(1)
将在第二天正确导致'0:00'。
答案 3 :(得分:4)
到此为止!
var rounded = date.AddMinutes(30).Date.AddHours(date.AddMinutes(30).Hour);
对于那些想要它的人来说
var floored = date.Date.AddHours(date.Hours)
答案 4 :(得分:3)
DateTime s = DateTime.Now;
if (s.Minute > 30) s = s.AddHours(1); //only add hours if > 30
if (s.Minute == 30 && s.Second > 0) s = s.AddHours(1); //add precision as needed
s = new DateTime(s.Year, s.Month, s.Day, s.Hour, 0, 0);
答案 5 :(得分:3)
扩展Hans Kestings好答案:
public DateTime RoundToHours(DateTime input)
{
DateTime dt = new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0);
return dt.AddHours((int)(input.Minutes / 30));
}
可能不需要(int)Cast。
编辑:修改了Hans Kesting在答案中所做的更正。
答案 6 :(得分:3)
为了改进其他一些方法,这里有一个方法也将保留DateTime种类:
/// <summary>
/// Rounds a DateTime to the nearest hour.
/// </summary>
/// <param name="dateTime">DateTime to Round</param>
/// <returns>DateTime rounded to nearest hour</returns>
public static DateTime RoundToNearestHour(this DateTime dateTime)
{
dateTime += TimeSpan.FromMinutes(30);
return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, 0, 0, dateTime.Kind);
}
答案 7 :(得分:1)
DateTime dtm = DateTime.Now;
if (dtm.Minute < 30)
{
dtm = dtm.AddMinutes(dtm.Minute * -1);
}
else
{
dtm = dtm.AddMinutes(60 - dtm.Minute);
}
dtm = dtm.AddSeconds(dtm.Second * -1);
答案 8 :(得分:1)
基于P Daddy的解决方案,我建议不要将大量的刻度硬编码到一小时。硬编码是邪恶的,不是吗?使用此修改后的解决方案,您现在可以将任何给定时间舍入为任意分钟数:
public DateTime RoundToMinutes(DateTime dt, int NrMinutes)
{
long TicksInNrMinutes = (long)NrMinutes * 60 * 10000000;//1 tick per 100 nanosecond
long ticks = dt.Ticks + TicksInNrMinutes / 2;
return new DateTime(ticks - ticks % TicksInNrMinutes, dt.Kind);
}
我用它来四舍五入到最接近的5分钟,例如22:23变为22:25。
多年前,我使用相同的方法将金额汇总到最接近的25美分,例如22.23美元变成22.25美元。但项目经理有时会改变主意,但将四舍五入改为最接近的10或5美分将是微不足道的。所以现在我同样不必紧张,因为我的项目mgr需要将舍入时间缩短到另一轮nr分钟。
因此,这种舍入方法既快速又灵活。
我的方法已在this 2008 SO solution
中找到并发布