Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我怎样才能把时间凑到最接近的X分钟?_C#_Datetime_Rounding - Fatal编程技术网

C# 我怎样才能把时间凑到最接近的X分钟?

C# 我怎样才能把时间凑到最接近的X分钟?,c#,datetime,rounding,C#,Datetime,Rounding,是否有一个简单的函数将日期时间四舍五入到最接近的15分钟 例如 2011-08-11 16:59变为2011-08-11 17:00 2011-08-11 17:00保持为2011-08-11 17:00 2011-08-11 17:01变为2011-08-11 17:15 DateTime RoundUp(DateTime dt, TimeSpan d) { return new DateTime((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks

是否有一个简单的函数将日期时间四舍五入到最接近的15分钟

例如

2011-08-11 16:59
变为
2011-08-11 17:00

2011-08-11 17:00
保持为
2011-08-11 17:00

2011-08-11 17:01
变为
2011-08-11 17:15

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

优雅

dt.AddSeconds(900 - (x.Minute * 60 + x.Second) % 900)
结果:

8/11/2011 5:00:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:00:00 PM

因为我讨厌重新发明轮子,我可能会按照这个算法将日期时间值四舍五入到指定的时间增量(Timespan):

  • 将要舍入的
    DateTime
    值转换为十进制浮点值,表示
    TimeSpan
    单位的整数和小数
  • 使用
    Math.Round()
    将其四舍五入为整数
  • 将取整的整数乘以
    TimeSpan
    单位中的刻度数,以缩小刻度
  • 从四舍五入的刻度数中实例化一个新的
    DateTime
    值,并将其返回给调用者
代码如下:

public static class DateTimeExtensions
{

    public static DateTime Round( this DateTime value , TimeSpan unit )
    {
        return Round( value , unit , default(MidpointRounding) ) ;
    }

    public static DateTime Round( this DateTime value , TimeSpan unit , MidpointRounding style )
    {
        if ( unit <= TimeSpan.Zero ) throw new ArgumentOutOfRangeException("unit" , "value must be positive") ;

        Decimal  units        = (decimal) value.Ticks / (decimal) unit.Ticks ;
        Decimal  roundedUnits = Math.Round( units , style ) ;
        long     roundedTicks = (long) roundedUnits * unit.Ticks ;
        DateTime instance     = new DateTime( roundedTicks ) ;

        return instance ;
    }

}
公共静态类DateTimeExtensions
{
公共静态日期时间轮(此日期时间值,时间跨度单位)
{
返回舍入(值、单位、默认值(中点舍入));
}
公共静态日期时间舍入(此日期时间值、时间跨度单位、中点舍入样式)
{

如果(单位如果您需要四舍五入到最近的时间间隔(不超过) 那么我建议使用以下方法

    static DateTime RoundToNearestInterval(DateTime dt, TimeSpan d)
    {
        int f=0;
        double m = (double)(dt.Ticks % d.Ticks) / d.Ticks;
        if (m >= 0.5)
            f=1;            
        return new DateTime(((dt.Ticks/ d.Ticks)+f) * d.Ticks);
    }

注意:上述公式不正确,即:

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

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

提出了一个解决方案,该方案不涉及相乘和相除
数字

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

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

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

    return new DateTime(dt.Ticks + offset - delta, dt.Kind);
}
用法:

var date = new DateTime(2010, 02, 05, 10, 35, 25, 450); // 2010/02/05 10:35:25
var roundedUp = date.RoundUp(TimeSpan.FromMinutes(15)); // 2010/02/05 10:45:00
var roundedDown = date.RoundDown(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00
var roundedToNearest = date.RoundToNearest(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00

更详细的解决方案,使用模运算,避免不必要的计算

public static class DateTimeExtensions
{
    public static DateTime RoundUp(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, true);
    }

    public static DateTime RoundDown(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, false);
    }

    private static DateTime Round(DateTime dt, TimeSpan ts, bool up)
    {
        var remainder = dt.Ticks % ts.Ticks;
        if (remainder == 0)
        {
            return dt;
        }

        long delta;
        if (up)
        {
            delta = ts.Ticks - remainder;
        }
        else
        {
            delta = -remainder;
        }

        return dt.AddTicks(delta);
    }
}

这是一个简单的解决方案,可以将时间四舍五入到最接近的1分钟。它保留日期时间的时区和种类信息。可以对其进行修改以进一步满足您自己的需要(如果您需要四舍五入到最接近的5分钟等)


您可以使用此方法,它使用指定的日期来确保它维护先前在datetime对象中指定的任何全球化和datetime类型

const long LNG_OneMinuteInTicks = 600000000;
/// <summary>
/// Round the datetime to the nearest minute
/// </summary>
/// <param name = "dateTime"></param>
/// <param name = "numberMinutes">The number minute use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, int numberMinutes = 1)
{
    long roundedMinutesInTicks = LNG_OneMinuteInTicks * numberMinutes;
    long remainderTicks = dateTime.Ticks % roundedMinutesInTicks;
    if (remainderTicks < roundedMinutesInTicks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundedMinutesInTicks - remainderTicks);
}
const long LNG\u oneminuteincks=600000000;
/// 
///将日期时间四舍五入到最近的一分钟
/// 
/// 
///用于将时间四舍五入到的分钟数
///         
公共静态DateTime轮(DateTime DateTime,int numberMinutes=1)
{
长循环分钟数=LNG_一分钟数*编号;
long remainderTicks=dateTime.Ticks%roundedMinutesInTicks;
如果(剩余刻度

如果要使用时间跨度进行取整,可以使用此选项

/// <summary>
/// Round the datetime
/// </summary>
/// <example>Round(dt, TimeSpan.FromMinutes(5)); => round the time to the nearest 5 minutes.</example>
/// <param name = "dateTime"></param>
/// <param name = "roundBy">The time use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, TimeSpan roundBy)
{            
    long remainderTicks = dateTime.Ticks % roundBy.Ticks;
    if (remainderTicks < roundBy.Ticks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundBy.Ticks - remainderTicks);
}
//
///全天
/// 
///舍入(dt,TimeSpan.frommins(5));=>将时间舍入到最接近的5分钟。
/// 
///将时间四舍五入到
///         
公共静态DateTime Round(DateTime DateTime,TimeSpan roundBy)
{            
long remainderTicks=dateTime.Ticks%roundBy.Ticks;
如果(剩余刻度
我的版本

DateTime newDateTimeObject = oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);
作为一种方法,它会像这样锁定

public static DateTime GetNextQuarterHour(DateTime oldDateTimeObject)
{
    return oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);
}
就这样叫

DateTime thisIsNow = DateTime.Now;
DateTime nextQuarterHour = GetNextQuarterHour(thisIsNow);
使用DateTime.MaxValue检查的解决方案:

DateTime RoundUp(DateTime dt, TimeSpan d) =>
    dt switch
    {
        var max when max.Equals(DateTime.MaxValue) => max,
        var v => new DateTime((v.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, v.Kind)
    };

我的DateTimeOffset版本,基于Ramon的回答:

public static class DateExtensions
{
    public static DateTimeOffset RoundUp(this DateTimeOffset dt, TimeSpan d)
    {
        return new DateTimeOffset((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, dt.Offset);
    }
}
您可以尝试以下方法:

string[] parts = ((DateTime)date_time.ToString("HH:mm:ss").Split(':');
int hr = Convert.ToInt32(parts[0]);
int mn = Convert.ToInt32(parts[1]);
int sec2min = (int)Math.Round(Convert.ToDouble(parts[2]) / 60.0, 0);

string adjTime = string.Format("1900-01-01 {0:00}:{1:00}:00.000",
(mn + sec2min > 59 ? (hr + 1 > 23 ? 0 : hr + 1) : hr),
 mn + sec2min > 59 ? 60 - mn + sec2min : mn + sec2min);
每个部分(hr,min)必须递增,并调整到适当的溢出值,如59 min>00,然后将1添加到hr,如果是23,则hr变为00。
例如,07:34:57四舍五入到07:35,09:59:45四舍五入到10:00,23:59:45四舍五入到00:00,这是第二天的时间。

我看到了许多有用的实现,比如@dtb或@redent84中的实现。 由于性能差异可以忽略不计,所以我远离位移位,只创建可读代码。我经常在实用程序库中使用这些扩展

public static class DateTimeExtensions
{
    public static DateTime RoundToTicks(this DateTime target, long ticks) => new DateTime((target.Ticks + ticks / 2) / ticks * ticks, target.Kind);
    public static DateTime RoundUpToTicks(this DateTime target, long ticks) => new DateTime((target.Ticks + ticks - 1) / ticks * ticks, target.Kind);
    public static DateTime RoundDownToTicks(this DateTime target, long ticks) => new DateTime(target.Ticks / ticks * ticks, target.Kind);

    public static DateTime Round(this DateTime target, TimeSpan round) => RoundToTicks(target, round.Ticks);
    public static DateTime RoundUp(this DateTime target, TimeSpan round) => RoundUpToTicks(target, round.Ticks);
    public static DateTime RoundDown(this DateTime target, TimeSpan round) => RoundDownToTicks(target, round.Ticks);

    public static DateTime RoundToMinutes(this DateTime target, int minutes = 1) => RoundToTicks(target, minutes * TimeSpan.TicksPerMinute);
    public static DateTime RoundUpToMinutes(this DateTime target, int minutes = 1) => RoundUpToTicks(target, minutes * TimeSpan.TicksPerMinute);
    public static DateTime RoundDownToMinutes(this DateTime target, int minutes = 1) => RoundDownToTicks(target, minutes * TimeSpan.TicksPerMinute);

    public static DateTime RoundToHours(this DateTime target, int hours = 1) => RoundToTicks(target, hours * TimeSpan.TicksPerHour);
    public static DateTime RoundUpToHours(this DateTime target, int hours = 1) => RoundUpToTicks(target, hours * TimeSpan.TicksPerHour);
    public static DateTime RoundDownToHours(this DateTime target, int hours = 1) => RoundDownToTicks(target, hours * TimeSpan.TicksPerHour);


    public static DateTime RoundToDays(this DateTime target, int days = 1) => RoundToTicks(target, days * TimeSpan.TicksPerDay);
    public static DateTime RoundUpToDays(this DateTime target, int days = 1) => RoundUpToTicks(target, days * TimeSpan.TicksPerDay);
    public static DateTime RoundDownToDays(this DateTime target, int days = 1) => RoundDownToTicks(target, days * TimeSpan.TicksPerDay);
}

更正确的版本是:x.AddSeconds(900-(x.AddSeconds(-1).Minute*60+x.AddSeconds(-1.Second)%900)。AddSeconds(-1),用于处理“停留”条件。此解决方案只是作为扩展方法进入我的实用程序库。请注意接近上限的舍入时间。如果计算的刻度大于DateTime.MaxValue.Ticks,则可能会引发异常。请注意安全,并取计算值和DateTime.MaxValue.Ticks中的最小值。不是吗使用此方法从DateTime对象丢失信息?如种类和时区,如果设置了?@user14..(+d.Ticks-1)确保必要时将其取整。和*取整。示例将12取整到下一个5:(12+5-1)=16,16/5=3(因为它是整数数据类型),3*5=15。tada:)@dtb是一个小的添加,否则它可能有点问题:您需要保留datetime种类;-)
datetime汇总(datetime dt,TimeSpan d){返回新的日期时间(((dt.Ticks+d.Ticks-1)/d.Ticks)*d.Ticks,dt.kind);}
2011-08-11 17:00:01
被截断为
2011-08-11 17:00:00
@JYelton:谢谢你指出+1。我更改了我的代码以适应这一点。为方便验证提供代码Linqpad格式是一个非常节省时间的方法。非常容易使用。这是一个很好的代码,可以四舍五入到最近的
日期时间,但我也希望将
单位
四舍五入为倍数的能力。传入
中点舍入。从零开始
舍入
并没有达到预期效果。接受
中点舍入
参数,您还有其他想法吗?我确信这一点
public static class DateExtensions
{
    public static DateTimeOffset RoundUp(this DateTimeOffset dt, TimeSpan d)
    {
        return new DateTimeOffset((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, dt.Offset);
    }
}
string[] parts = ((DateTime)date_time.ToString("HH:mm:ss").Split(':');
int hr = Convert.ToInt32(parts[0]);
int mn = Convert.ToInt32(parts[1]);
int sec2min = (int)Math.Round(Convert.ToDouble(parts[2]) / 60.0, 0);

string adjTime = string.Format("1900-01-01 {0:00}:{1:00}:00.000",
(mn + sec2min > 59 ? (hr + 1 > 23 ? 0 : hr + 1) : hr),
 mn + sec2min > 59 ? 60 - mn + sec2min : mn + sec2min);
public static class DateTimeExtensions
{
    public static DateTime RoundToTicks(this DateTime target, long ticks) => new DateTime((target.Ticks + ticks / 2) / ticks * ticks, target.Kind);
    public static DateTime RoundUpToTicks(this DateTime target, long ticks) => new DateTime((target.Ticks + ticks - 1) / ticks * ticks, target.Kind);
    public static DateTime RoundDownToTicks(this DateTime target, long ticks) => new DateTime(target.Ticks / ticks * ticks, target.Kind);

    public static DateTime Round(this DateTime target, TimeSpan round) => RoundToTicks(target, round.Ticks);
    public static DateTime RoundUp(this DateTime target, TimeSpan round) => RoundUpToTicks(target, round.Ticks);
    public static DateTime RoundDown(this DateTime target, TimeSpan round) => RoundDownToTicks(target, round.Ticks);

    public static DateTime RoundToMinutes(this DateTime target, int minutes = 1) => RoundToTicks(target, minutes * TimeSpan.TicksPerMinute);
    public static DateTime RoundUpToMinutes(this DateTime target, int minutes = 1) => RoundUpToTicks(target, minutes * TimeSpan.TicksPerMinute);
    public static DateTime RoundDownToMinutes(this DateTime target, int minutes = 1) => RoundDownToTicks(target, minutes * TimeSpan.TicksPerMinute);

    public static DateTime RoundToHours(this DateTime target, int hours = 1) => RoundToTicks(target, hours * TimeSpan.TicksPerHour);
    public static DateTime RoundUpToHours(this DateTime target, int hours = 1) => RoundUpToTicks(target, hours * TimeSpan.TicksPerHour);
    public static DateTime RoundDownToHours(this DateTime target, int hours = 1) => RoundDownToTicks(target, hours * TimeSpan.TicksPerHour);


    public static DateTime RoundToDays(this DateTime target, int days = 1) => RoundToTicks(target, days * TimeSpan.TicksPerDay);
    public static DateTime RoundUpToDays(this DateTime target, int days = 1) => RoundUpToTicks(target, days * TimeSpan.TicksPerDay);
    public static DateTime RoundDownToDays(this DateTime target, int days = 1) => RoundDownToTicks(target, days * TimeSpan.TicksPerDay);
}