Answers:
以下内容适用于具有小数毫秒的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
...
var 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
。因此它还没有被截断到整秒。
有时您想要截断为基于日历的内容,例如年或月。这是一种扩展方法,可让您选择任何分辨率。
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;
不太明显,但快了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);
d.AddMilliseconds(-d.Millisecond)
不一定会将DateTime精确地移到前一秒。d.Ticks % TimeSpan.TicksPerMillisecond
超过秒数的滴答声(0到9,999之间的某个滴答声)将保留。
向下舍入到第二个:
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时间。
一种易于阅读的方法是...
//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())
效果很好。
关于Diadistis反应。这对我有用,除了在乘法之前我必须使用Floor删除除法的小数部分。所以,
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
变成
d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
我本来希望两个Long值的除法会导致Long,从而删除了小数部分,但是它将其解析为Double,而在乘法之后却留下了完全相同的值。
癫痫病
2上述解决方案的扩展方法
public static bool LiesAfterIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind)
{
DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind);
compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind);
return thisDate > compareDate;
}
public static bool LiesAfterOrEqualsIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind)
{
DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind);
compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind);
return thisDate >= compareDate;
}
用法:
bool liesAfter = myObject.DateProperty.LiesAfterOrEqualsIgnoringMilliseconds(startDateTime, DateTimeKind.Utc);
就我而言,我的目标是从datetimePicker工具保存TimeSpan而不保存秒和毫秒,这是解决方案。
首先将datetimePicker.value转换为所需的格式,即“ HH:mm”,然后将其转换回TimeSpan。
var datetime = datetimepicker1.Value.ToString("HH:mm");
TimeSpan timeSpan = Convert.ToDateTime(datetime).TimeOfDay;
这是我在此处发布的扩展方法版本,并且存在类似问题。这以一种易于阅读的方式验证了ticks值,并保留了原始DateTime实例的DateTimeKind。(当存储到MongoDB之类的数据库时,这具有微妙但相关的副作用。)
如果真正的目标是将DateTime截断为指定的值(例如Hours / Minutes / Seconds / 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;
// /programming/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 currentDateTime = DateTime.Now.ToString("s");
尝试打印该变量的值,它将显示日期时间,而不是毫秒。
string
的表示DateTime
,也许需要编辑,使其明确指出,要“截断” /“滴”毫秒装置“产生一个DateTime
值,其中所有日期/时间组件是除了同一TimeOfDay.TotalMilliseconds
是0
”。人们当然不会读书,只是为了消除任何歧义。