如何截断.NET DateTime的毫秒数

时间:2009-06-17 01:43:19

标签: c# .net datetime

我正在尝试将传入请求的时间戳与数据库存储值进行比较。 SQL Server当然会保留一些毫秒的精度,当读入.NET DateTime时,它包括那些毫秒。但是,对系统的传入请求不提供该精度,因此我只需要删除毫秒。

我觉得我错过了一些明显的东西,但我还没有找到一种优雅的方法(C#)。

16 个答案:

答案 0 :(得分:506)

以下内容适用于具有小数毫秒的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
...

答案 1 :(得分:131)

var date = DateTime.Now;

date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);

答案 2 :(得分:48)

这是一个基于前一个答案的扩展方法,可以让你截断到任何分辨率......

<强>用法:

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);
    }
}

答案 3 :(得分:27)

DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);

答案 4 :(得分:9)

为什么不比较差异,而不是减去毫秒然后比较?

DateTime x; DateTime y;
bool areEqual = (x-y).TotalSeconds == 0;

TimeSpan precision = TimeSpan.FromSeconds(1);
bool areEqual = (x-y).Duration() < precision;

答案 5 :(得分:8)

不太明显,但速度提高了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);

答案 6 :(得分:8)

有时您希望截断为基于日历的内容,例如年份或月份。这是一种扩展方法,可让您选择任何分辨率。

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");
    }
}

答案 7 :(得分:2)

不是最快的解决方案,但简单易懂:

DateTime d = DateTime.Now;
d = d.Date.AddHours(d.Hour).AddMinutes(d.Minute).AddSeconds(d.Second)

答案 8 :(得分:1)

关于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,在乘法后保留完全相同的值。

Eppsy

答案 9 :(得分:1)

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);

答案 10 :(得分:1)

DateID.Text = DateTime.Today.ToShortDateString();

Use ToShortDateString() //Date 2-02-2016
Use ToShortDateString() // Time 

并使用

ToLongDateString() // its show 19 February 2016.

:P

答案 11 :(得分:1)

新方法

String Date = DateTime.Today.ToString("dd-MMM-yyyy"); 

// define String pass参数dd-mmm-yyyy return 24-feb-2016

或在文本框中显示

txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy");

//放在PageonLoad

答案 12 :(得分:1)

向下舍入到第二个:

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时间。

答案 13 :(得分:1)

这是我在此处和类似问题中发布的扩展方法版本。这以易于阅读的方式验证了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;

    // 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

答案 14 :(得分:0)

对于我来说,我的目标是从datetimePicker工具中保存TimeSpan而不保存秒和毫秒,这是解决方法。

首先将datetimePicker.value转换为所需的格式,即“ HH:mm”,然后将其转换回TimeSpan。

var datetime = datetimepicker1.Value.ToString("HH:mm");
TimeSpan timeSpan = Convert.ToDateTime(datetime).TimeOfDay;

答案 15 :(得分:-1)

我知道答案还很晚,但是摆脱毫秒的最佳方法是

var currentDateTime = DateTime.Now.ToString("s");

尝试打印该变量的值,它将显示日期时间,而不是毫秒。