Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何截断.NET日期时间的毫秒数_C#_.net_Datetime - Fatal编程技术网

C# 如何截断.NET日期时间的毫秒数

C# 如何截断.NET日期时间的毫秒数,c#,.net,datetime,C#,.net,Datetime,我试图将传入请求的时间戳与数据库存储值进行比较。SQL Server当然会保持毫秒的时间精度,当读入.NET DateTime时,它会包含这些毫秒。但是,系统的传入请求不提供该精度,因此我只需删除毫秒 我觉得我遗漏了一些明显的东西,但我还没有找到一种优雅的方法来做(C#)。与其降低毫秒数,然后进行比较,为什么不比较差异 DateTime x; DateTime y; bool areEqual = (x-y).TotalSeconds == 0; 或 TimeSpan precision=Ti

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


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

与其降低毫秒数,然后进行比较,为什么不比较差异

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

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

不太明显,但速度快了两倍以上:

// 10000000 runs

DateTime d = DateTime.Now;

// 484,375ms
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);

// 1296,875ms
d = d.AddMilliseconds(-d.Millisecond);

以下内容适用于具有小数毫秒的DateTime,并且还保留了Kind属性(Local、Utc或Undefined)

或同等或更短的:

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

关于重分类反应。这对我来说很有效,除了在乘法之前我必须使用Floor删除除法的小数部分。所以

d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
变成

d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
我本以为两个长值的除法会产生一个长值,从而去掉小数部分,但它将其解析为一个双精度,在乘法后留下完全相同的值


Eppsy

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

用法:

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 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);
    }
}
公共静态类DateTimeUtils
{
/// 
///将日期时间截断为指定的分辨率。
///一个方便的解析源是TimeSpan.TicksPerXXXX常量。
/// 
///要截断的DateTime对象
///例如,四舍五入到最接近的秒,TimeSpan.TicksPerSecond
///截断日期时间
公共静态日期时间截断(此日期时间日期,长分辨率)
{
返回新的日期时间(date.Ticks-(date.Ticks%分辨率),date.Kind);
}
}

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

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

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

一个简单的阅读方法是

//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...
利用

ToLongDateString() // its show 19 February 2016.
:p

新方法

String Date = DateTime.Today.ToString("dd-MMM-yyyy"); 
//定义字符串传递参数dd mmm yyyy返回2016年2月24日

或显示在文本框上

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

//打开PageonLoad

,四舍五入到第二位:

dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)
替换为
滴答声分钟
,四舍五入到分钟


如果您的代码对性能敏感,请谨慎使用

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

我的应用程序花费了12%的CPU时间。

在我的例子中,我的目标是从datetimePicker工具中节省时间跨度,而不节省秒数和毫秒数,下面是解决方案

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

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

我知道答案已经很晚了,但最好的办法是

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

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

这是我在这里和类似问题中发布的扩展方法版本。这将以易于读取的方式验证ticks值,并保留原始DateTime实例的DateTimeKind。(在存储到MongoDB之类的数据库时,这会产生微妙但相关的副作用。)

如果真正的目标是将日期时间截断为指定值(即小时/分钟/秒/毫秒),我建议在代码中实现此扩展方法。它确保您只能截断到有效的精度,并保留原始实例的重要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

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

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

-1:仅当DateTime值不包含毫秒分数时才有效。使用此方法导致我的一些单元测试失败:预期:2010-05-05 15:55:49.000,但was:2010-05-05 15:55:49.000。我猜是因为Joe提到的毫秒分数。不适用于序列化,例如,2010-12-08T11:20:03.000099+15:00是输出,没有完全切掉毫秒。给出了一个介于0和999(包括)之间的整数。因此,如果操作前一天的时间是,比如说,
23:48:49.1234567
,那么该整数将是
123
,操作后一天的时间是
23:48:49.0004567
。所以它并没有被截断到整秒。虽然我给你这个,因为你在技术上是正确的,但是对于从SQL Server读取数据的人来说,与一些分布式数据(在我的例子中是基于Web的请求)进行比较,这个解析量是不必要的。很好。显然,有人需要为DateTime类提供一些扩展方法,使其舍入到最接近的值,以便重用这种类型的良好编码。这是不太可能的,但当ticks=0时,这种方法不会中断吗?@adotout,如果timeSpan参数为零,上面的Truncate方法将抛出dividebyzero异常,这就是你所说的“滴答声=0时接近中断”的意思吗?最好在timeSpan为零时抛出ArgumentException。您真的应该忽略DateTime.MinValue和DataTime.MaxValue吗?如果有人显式使用
DateTime.MaxValue.Truncate(TimeSpan.FromSeconds(1))
我希望它会按照tin上的说明执行。第一个选项不起作用,因为TotalSeconds是双精度的;它还返回毫秒数。比较差异不会得到与截断然后比较相同的结果。例如,5.900和6.100相距不到一秒,因此将与您的方法进行同等比较。但是截断值5和6是不同的。根据您的要求选择合适的。简单明了,只需记住添加一个“、日期、种类”
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
DateTime d = DateTime.Now;
d = d.Date.AddHours(d.Hour).AddMinutes(d.Minute).AddSeconds(d.Second)