我正在尝试比较来自传入请求的时间戳和数据库存储值。当然,SQL Server在时间上保持一些毫秒的精度,当读取到. net DateTime时,它包含了这些毫秒。但是,传入系统的请求不能提供这样的精度,所以我只需要去掉毫秒。
我觉得我遗漏了一些明显的东西,但我还没有找到一种优雅的方法来做到这一点(c#)。
我正在尝试比较来自传入请求的时间戳和数据库存储值。当然,SQL Server在时间上保持一些毫秒的精度,当读取到. net DateTime时,它包含了这些毫秒。但是,传入系统的请求不能提供这样的精度,所以我只需要去掉毫秒。
我觉得我遗漏了一些明显的东西,但我还没有找到一种优雅的方法来做到这一点(c#)。
当前回答
不是最快的解决方案,但简单易懂:
DateTime d = DateTime.Now;
d = d.Date.AddHours(d.Hour).AddMinutes(d.Minute).AddSeconds(d.Second)
其他回答
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
不那么明显,但快了2倍多:
// 10000000 runs
DateTime d = DateTime.Now;
// 484,375ms
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
// 1296,875ms
d = d.AddMilliseconds(-d.Millisecond);
这是我的版本的扩展方法张贴在这里和类似的问题。这将以一种易于读取的方式验证tick值,并保留原始DateTime实例的DateTimeKind。(当存储到像MongoDB这样的数据库时,这有微妙但相关的副作用。)
如果真正的目标是将DateTime截断为指定的值(即小时/分钟/秒/MS),我建议在您的代码中实现此扩展方法。它确保你只能截断到一个有效的精度,它保留了重要的DateTimeKind元数据的原始实例:
public static DateTime Truncate(this DateTime dateTime, long ticks)
{
bool isValid = ticks == TimeSpan.TicksPerDay
|| ticks == TimeSpan.TicksPerHour
|| ticks == TimeSpan.TicksPerMinute
|| ticks == TimeSpan.TicksPerSecond
|| ticks == TimeSpan.TicksPerMillisecond;
// https://stackoverflow.com/questions/21704604/have-datetime-now-return-to-the-nearest-second
return isValid
? DateTime.SpecifyKind(
new DateTime(
dateTime.Ticks - (dateTime.Ticks % ticks)
),
dateTime.Kind
)
: throw new ArgumentException("Invalid ticks value given. Only TimeSpan tick values are allowed.");
}
然后你可以使用这样的方法:
DateTime dateTime = DateTime.UtcNow.Truncate(TimeSpan.TicksPerMillisecond);
dateTime.Kind => DateTimeKind.Utc
var date = DateTime.Now;
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
以下将适用于具有分数毫秒的DateTime,并保留Kind属性(Local, Utc或Undefined)。
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
if (dateTime == DateTime.MinValue || dateTime == 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
...