如何将日期时间舍入到最接近的200毫秒?

时间:2018-05-22 15:24:53

标签: c# .net

在我写的C#.Net应用程序中,我希望将一些DateTime值舍入到最接近的200毫秒。我提出了以下代码;

   public static DateTime RoundToTheTwoHundredthMillisecond(DateTime dt) {            
        var ms = dt.Millisecond;
        var s = dt.Second;
        var m = dt.Minute;
        var h = dt.Hour;
        var d = dt.Day;
        var M = dt.Month;
        var y = dt.Year;
        if (ms >= 900 && ms < 1000) ms = 1000; 
        if (ms >= 700 && ms < 900) ms = 800;
        if (ms >= 500 && ms < 700) ms = 600;
        if (ms >= 300 && ms < 500) ms = 400;
        if (ms >= 100 && ms < 300) ms = 200;
        if (ms >= 0 && ms < 100) ms = 0;

        // 1000 is an invalid millisecond. We need to round up a second. Use AddSeconds so it will automatically roll up should we be 1 second away from a new minute, 1 minute away from a new hour...etc...leap years and months are handled also....
        if (ms == 1000) {                
            return new DateTime(y, M, d, m, h, s, 0, dt.Kind).AddSeconds(1);
        } 
        else {
            return new DateTime(y, M, d, m, h, s, ms, dt.Kind);
        }                     
    }

认为它可能正常运作。但我想知道是否有人能指出一种可能比我的摸索更可靠的方法?或者,这可能是/应该编写单元测试的东西? (这样做似乎也容易让我自己摸索)

2 个答案:

答案 0 :(得分:2)

你可以用200除以圆,然后再乘以得到值。您也可以从原始DateTime中减去差异,无需重新构建组件。

public static DateTime RoundToTheTwoHundredthMillisecond(DateTime dt)
{
    var ms = Math.Round(dt.Millisecond / 200.0) * 200;
    return dt.AddMilliseconds(ms- dt.Millisecond);
}

修改

要模仿我们可以使用if

的确切MidpointRounding序列
public static DateTime RoundToTheTwoHundredthMillisecond(DateTime dt)
{
    var ms = Math.Round(dt.Millisecond / 200.0, MidpointRounding.ToEven) * 200;
    return dt.AddMilliseconds(ms- dt.Millisecond);
}

答案 1 :(得分:1)

您可以使用此表达式(有错误)

var value = DateTime.Now;
var roundedValue = DateTime.MinValue + TimeSpan.FromMilliseconds(((((long)((value - DateTime.MinValue).TotalMilliseconds) + 199) / 200) * 200)));

更新: 使用较少括号的正确代码;)

class Program
{
    static void Main(string[] args)
    {
        for (int index = 0; index < 20; ++index)
        {
            System.Threading.Thread.Sleep(349);
            DateTime value = DateTime.Now;
            DateTime rounded = value.RoundTo200thMillisecond();
            Console.WriteLine($"value = {value:yyyy-MM-dd HH:mm:ss.fff}, rounded = {rounded:yyyy-MM-dd HH:mm:ss.fff}");
        }
    }
}

public static class DateTimeExtensions
{
    public static DateTime RoundTo200thMillisecond(this DateTime value)
    {
        long elapsed = (long)((value - DateTime.MinValue).TotalMilliseconds);
        return DateTime.MinValue + TimeSpan.FromMilliseconds((elapsed + 100) / 200 * 200);
    }
}

输出中:

value = 2018-05-22 21:50:38.174, rounded = 2018-05-22 21:50:38.200
value = 2018-05-22 21:50:38.534, rounded = 2018-05-22 21:50:38.600
value = 2018-05-22 21:50:38.893, rounded = 2018-05-22 21:50:38.800
value = 2018-05-22 21:50:39.252, rounded = 2018-05-22 21:50:39.200
value = 2018-05-22 21:50:39.612, rounded = 2018-05-22 21:50:39.600
value = 2018-05-22 21:50:39.971, rounded = 2018-05-22 21:50:40.000
value = 2018-05-22 21:50:40.330, rounded = 2018-05-22 21:50:40.400
value = 2018-05-22 21:50:40.690, rounded = 2018-05-22 21:50:40.600
value = 2018-05-22 21:50:41.049, rounded = 2018-05-22 21:50:41.000
value = 2018-05-22 21:50:41.409, rounded = 2018-05-22 21:50:41.400
value = 2018-05-22 21:50:41.768, rounded = 2018-05-22 21:50:41.800
value = 2018-05-22 21:50:42.127, rounded = 2018-05-22 21:50:42.200
value = 2018-05-22 21:50:42.487, rounded = 2018-05-22 21:50:42.400
value = 2018-05-22 21:50:42.846, rounded = 2018-05-22 21:50:42.800
value = 2018-05-22 21:50:43.206, rounded = 2018-05-22 21:50:43.200
value = 2018-05-22 21:50:43.565, rounded = 2018-05-22 21:50:43.600
value = 2018-05-22 21:50:43.924, rounded = 2018-05-22 21:50:44.000
value = 2018-05-22 21:50:44.284, rounded = 2018-05-22 21:50:44.200
value = 2018-05-22 21:50:44.643, rounded = 2018-05-22 21:50:44.600
value = 2018-05-22 21:50:45.002, rounded = 2018-05-22 21:50:45.000