C# 中是否有更好的方法将 DateTime 舍入到最接近的 5 秒?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/766626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a better way in C# to round a DateTime to the nearest 5 seconds?
提问by Damovisa
I want to round a DateTime to the nearest 5 seconds. This is the way I'm currently doing it but I was wondering if there was a better or more concise way?
我想将 DateTime 舍入到最接近的 5 秒。这是我目前正在做的方式,但我想知道是否有更好或更简洁的方式?
DateTime now = DateTime.Now;
int second = 0;
// round to nearest 5 second mark
if (now.Second % 5 > 2.5)
{
// round up
second = now.Second + (5 - (now.Second % 5));
}
else
{
// round down
second = now.Second - (now.Second % 5);
}
DateTime rounded = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, second);
Please note that I've found thesetwoprevious questions, however they truncaterather than roundthe time.
采纳答案by JayMcClellan
The Ticks count of a DateTime represents 100-nanosecond intervals, so you can round to the nearest 5 seconds by rounding to the nearest 50000000-tick interval like this:
DateTime 的 Ticks 计数表示 100 纳秒的间隔,因此您可以通过四舍五入到最接近的 50000000-tick 间隔来四舍五入到最接近的 5 秒,如下所示:
DateTime now = DateTime.Now;
DateTime rounded = new DateTime(((now.Ticks + 25000000) / 50000000) * 50000000);
That's more concise, but not necessarily better. It depends on whether you prefer brevity and speed over code clarity. Yours is arguably easier to understand.
这样更简洁,但不一定更好。这取决于您是否更喜欢简洁和速度而不是代码清晰度。你的可以说更容易理解。
回答by Sophie Alpert
Like you mentioned, it's fairly easy to truncate. So, just add 2.5 seconds, then truncate down.
就像你提到的,截断很容易。所以,只需添加 2.5 秒,然后截断。
回答by RossFabricant
I can't think of a better way, although I would probably factor out the round method:
我想不出更好的方法,尽管我可能会考虑圆形方法:
static int Round(int n, int r)
{
if ((n % r) <= r / 2)
{
return n - (n % r);
}
return n + (r - (n % r));
}
Also, % returns an int, so comparing it to 2.5 strikes me as a little odd, even though it is correct. I'd use >= 3.
此外,% 返回一个 int,因此将它与 2.5 进行比较让我觉得有点奇怪,即使它是正确的。我会使用> = 3。
回答by paxdiablo
I couldn't recognize the difference between C# and a bar of soap (well, I couldn't when I originally wrote this answer, things have changed quite a bit in the years since) but, if you're looking for a more concisesolution, I would just put the whole thing in a function - there's little that will be more concise in your code than a simple call to said function:
我无法识别 C# 和一块肥皂之间的区别(好吧,当我最初写这个答案时我无法识别,从那时起,事情发生了很大的变化)但是,如果您正在寻找更简洁的解决方案,我只是将整个事情放在一个函数中 - 在您的代码中,没有什么比对所述函数的简单调用更简洁的了:
DateTime rounded = roundTo5Secs (DateTime.Now);
Then you can put whatever you want in the function and just document how it works, such as (assuming these are all integer operations):
然后你可以在函数中放入任何你想要的东西并记录它是如何工作的,例如(假设这些都是整数运算):
secBase = now.Second / 5;
secExtra = now.Second % 5;
if (secExtra > 2) {
return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute,
secBase + 5);
}
return new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute,
secBase);
You may also need some extra checks if secBase goes to 60 (unless C# DateTime objects are smart enough to bump up the minute (and hour if minute goes to 60, and so on).
如果 secBase 达到 60,您可能还需要一些额外的检查(除非 C# DateTime 对象足够智能以增加分钟(如果分钟达到 60,则为小时,依此类推)。
回答by Erich Mirabal
How about this (blending a few answers together)? I think it conveys the meaning well and should handle the edge cases (rounding to the next minute) elegantly due to AddSeconds
.
这个怎么样(混合几个答案)?我认为它很好地传达了含义并且应该优雅地处理边缘情况(四舍五入到下一分钟)由于AddSeconds
.
// truncate to multiple of 5
int second = 5 * (int) (now.Second / 5);
DateTime dt = new DateTime(..., second);
// round-up if necessary
if (now.Second % 5 > 2.5)
{
dt = dt.AddSeconds(5);
}
The Ticks
approach as shown by Jay is more concise, but may be a bit less readable. If you use that approach, at least reference TimeSpan.TicksPerSecond
.
Ticks
Jay 展示的方法更简洁,但可读性可能稍差一些。如果您使用这种方法,请至少参考TimeSpan.TicksPerSecond
.
回答by Matt Winckler
(Sorry for the resurrection; I recognize it's an old and answered question - just adding some extra code for Google's sake.)
(对不起,复活了;我知道这是一个古老的答案问题——只是为了谷歌添加了一些额外的代码。)
I started with JayMcClellan's answer, but then I wanted it to be more generic, rounding to arbitrary intervals (not just 5 seconds). So I ended up leaving Jay's method for one that uses Math.Round
on ticks and put it into an extension method that can take arbitrary intervals and also offers the option of changing the rounding logic (banker's rounding versus away-from-zero). I'm posting here in case this is helpful to someone else as well:
我从JayMcClellan's answer开始,但后来我希望它更通用,四舍五入到任意间隔(不仅仅是 5 秒)。因此,我最终将 Jay 的方法留给了一个Math.Round
在分时使用的方法,并将其放入可以采用任意间隔的扩展方法中,并且还提供了更改舍入逻辑的选项(银行家舍入与远离零的舍入)。我在这里发帖以防这对其他人也有帮助:
public static TimeSpan Round(this TimeSpan time, TimeSpan roundingInterval, MidpointRounding roundingType) {
return new TimeSpan(
Convert.ToInt64(Math.Round(
time.Ticks / (decimal)roundingInterval.Ticks,
roundingType
)) * roundingInterval.Ticks
);
}
public static TimeSpan Round(this TimeSpan time, TimeSpan roundingInterval) {
return Round(time, roundingInterval, MidpointRounding.ToEven);
}
public static DateTime Round(this DateTime datetime, TimeSpan roundingInterval) {
return new DateTime((datetime - DateTime.MinValue).Round(roundingInterval).Ticks);
}
It won't win any awards for bare efficiency, but I find it easy to read and intuitive to use. Example usage:
它不会因为纯粹的效率而赢得任何奖项,但我发现它易于阅读且使用直观。用法示例:
new DateTime(2010, 11, 4, 10, 28, 27).Round(TimeSpan.FromMinutes(1)); // rounds to 2010.11.04 10:28:00
new DateTime(2010, 11, 4, 13, 28, 27).Round(TimeSpan.FromDays(1)); // rounds to 2010.11.05 00:00
new TimeSpan(0, 2, 26).Round(TimeSpan.FromSeconds(5)); // rounds to 00:02:25
new TimeSpan(3, 34, 0).Round(TimeSpan.FromMinutes(37); // rounds to 03:42:00...for all your round-to-37-minute needs
回答by Jim K.
Technically, you can never correctly round to an odd interval given only seconds.
从技术上讲,您永远无法正确舍入到仅给定几秒钟的奇数间隔。
2, 4, 6, 8, 10 <-- are no problem
2, 4, 6, 8, 10 <-- 没问题
If you are 'distributing' times in intervals and if the jitter is low, truncation is a lot more tractable.
如果您按时间间隔“分配”时间并且抖动很低,则截断更容易处理。
If you can pass milliseconds and round at a 500mS mark, you will be able to to odd seconds and also slash the effect of jitter way down or eliminate it entirely.
如果您可以以 500 毫秒为单位传递毫秒和舍入,您将能够达到奇数秒,并且还可以减少或完全消除抖动的影响。