我正在尝试将传入请求的时间戳与数据库中存储的值进行比较。当从 SQL Server 读取时间时,它会保留毫秒的精度,并在读入 .NET DateTime 后包含这些毫秒。然而,系统传入的请求并没有提供那种精度,所以我需要简单地舍去毫秒。
我觉得我可能漏掉了一些显而易见的东西,但是我还没有找到一个简洁的方法来实现它(C#)。
DateTime dateTime = ... anything ...
dateTime = new DateTime(
dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond),
dateTime.Kind
);
dateTime = dateTime.AddTicks( - (dateTime.Ticks % TimeSpan.TicksPerSecond));
public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan)
{
if (timeSpan == TimeSpan.Zero) return dateTime; // Or could throw an ArgumentException
// Some comments suggest removing the following line. I think the check
// for MaxValue makes sense - it's often used to represent an indefinite expiry date.
// (The check for DateTime.MinValue has no effect, because DateTime.MinValue % timeSpan
// is equal to DateTime.MinValue for any non-zero value of timeSpan. But I think
// leaving the check in place makes the intent clearer).
// YMMV and the fact that different people have different expectations is probably
// part of the reason such a method doesn't exist in the Framework.
if (dateTime == DateTime.MinValue || DateTime.MaxValue) return dateTime; // do not modify "guard" values
return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks));
}
dateTime = dateTime.Truncate(TimeSpan.FromMilliseconds(1)); // Truncate to whole ms
dateTime = dateTime.Truncate(TimeSpan.FromSeconds(1)); // Truncate to whole second
dateTime = dateTime.Truncate(TimeSpan.FromMinutes(1)); // Truncate to whole minute
...
DateTime.MaxValue.Truncate(TimeSpan.FromSeconds(1))
,我期望它能够像字面上所说的那样工作。 - Alexvar date = DateTime.Now;
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
这是一个基于之前答案的扩展方法,它可以让你截断到任意分辨率...
用法:
DateTime myDateSansMilliseconds = myDate.Truncate(TimeSpan.TicksPerSecond);
DateTime myDateSansSeconds = myDate.Truncate(TimeSpan.TicksPerMinute)
类:
public static class DateTimeUtils
{
/// <summary>
/// <para>Truncates a DateTime to a specified resolution.</para>
/// <para>A convenient source for resolution is TimeSpan.TicksPerXXXX constants.</para>
/// </summary>
/// <param name="date">The DateTime object to truncate</param>
/// <param name="resolution">e.g. to round to nearest second, TimeSpan.TicksPerSecond</param>
/// <returns>Truncated DateTime</returns>
public static DateTime Truncate(this DateTime date, long resolution)
{
return new DateTime(date.Ticks - (date.Ticks % resolution), date.Kind);
}
}
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
Millisecond
属性 返回一个介于 0 到 999(包括边界)之间的 整数。因此,如果操作之前的时间是 23:48:49.1234567
,那么这个整数将是 123
,而操作之后的时间是 23:48:49.0004567
。所以它没有截断为整秒数。 - Jeppe Stig Nielsen有时候你想要按照日历基础来截断数据,比如年或月。下面是一个扩展方法,可以让你选择任意的截断精度。
public enum DateTimeResolution
{
Year, Month, Day, Hour, Minute, Second, Millisecond, Tick
}
public static DateTime Truncate(this DateTime self, DateTimeResolution resolution = DateTimeResolution.Second)
{
switch (resolution)
{
case DateTimeResolution.Year:
return new DateTime(self.Year, 1, 1, 0, 0, 0, 0, self.Kind);
case DateTimeResolution.Month:
return new DateTime(self.Year, self.Month, 1, 0, 0, 0, self.Kind);
case DateTimeResolution.Day:
return new DateTime(self.Year, self.Month, self.Day, 0, 0, 0, self.Kind);
case DateTimeResolution.Hour:
return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerHour));
case DateTimeResolution.Minute:
return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMinute));
case DateTimeResolution.Second:
return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerSecond));
case DateTimeResolution.Millisecond:
return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMillisecond));
case DateTimeResolution.Tick:
return self.AddTicks(0);
default:
throw new ArgumentException("unrecognized resolution", "resolution");
}
}
为什么不比较时间差,而是要去掉毫秒后再进行比较?
DateTime x; DateTime y;
bool areEqual = (x-y).TotalSeconds == 0;
或者TimeSpan precision = TimeSpan.FromSeconds(1);
bool areEqual = (x-y).Duration() < precision;
向下舍入到秒:
dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)
将其替换为TicksPerMinute
可将结果向下舍入至分钟。
如果您的代码对性能敏感,请谨慎考虑。
new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second)
我的应用程序在System.DateTime.GetDatePart中花费了12%的CPU时间。
不太显眼,但速度比原来快了两倍以上:
// 10000000 runs
DateTime d = DateTime.Now;
// 484,375ms
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
// 1296,875ms
d = d.AddMilliseconds(-d.Millisecond);
d.AddMilliseconds(-d.Millisecond)
并不一定将 DateTime 正好移动到前一个完整秒。您所选的那一秒之后的 d.Ticks % TimeSpan.TicksPerMillisecond
个滴答声(在 0 到 9,999 之间)仍会保留。 - Technetium这个解决方案不是最快的,但简单易懂:
DateTime d = DateTime.Now;
d = d.Date.AddHours(d.Hour).AddMinutes(d.Minute).AddSeconds(d.Second)
//Remove milliseconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss", null);
以及更多...
//Remove seconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm"), "yyyy-MM-dd HH:mm", null);
//Remove minutes
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH"), "yyyy-MM-dd HH", null);
//and go on...
我知道这很容易理解,但它缺乏性能。
var now = DateTime.Parse(DateTime.Now.ToString())
就可以正常工作。 - Grimm The Opiner
string
表示中的毫秒组件,也许需要编辑以明确表达“截断” / “删除”毫秒指的是“生成一个DateTime
值,其中所有日期/时间组件都相同,除了TimeOfDay.TotalMilliseconds
是0
。” 当然,并非所有人都会仔细阅读,但为了消除任何歧义,这样做很重要。 - Lance U. Matthews