如何根据分钟来计算小时数(小时+ 0,如果分钟<30,小时+ 1否则)?

时间:2010-03-23 11:35:34

标签: c# .net datetime rounding

我需要根据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"));
}

9 个答案:

答案 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

中找到并发布