我正在尝试将传入请求中的时间戳与数据库存储值进行比较。 SQL Server当然会在时间上保持毫秒级的精度,当读入.NET DateTime时,它会包含这些毫秒级。但是,对系统的传入请求没有提供这种精度,因此我只需要降低毫秒数即可。方式(C#)。

评论

(第3次尝试...)由于20%的答案(1、2、3)描述了如何从DateTime的格式化字符串表示形式中删除或删除毫秒部分,因此可能需要进行编辑以明确指出“ truncate” /“ drop”毫秒表示“产生一个DateTime值,其中所有日期/时间分量都相同,但TimeOfDay.TotalMilliseconds为0。”人们当然不会阅读,只是为了消除任何歧义。

#1 楼

以下内容将适用于具有小数毫秒的DateTime,并且还保留Kind属性(Local,Utc或Undefined)。
br />
DateTime dateTime = ... anything ...
dateTime = new DateTime(
    dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond), 
    dateTime.Kind
    );


可以概括为扩展方法: />
dateTime = dateTime.AddTicks( - (dateTime.Ticks % TimeSpan.TicksPerSecond));


评论


尽管我会因为技术上的正确而为您提供此信息,但对于从SQL Server读取数据以与某些分布式数据(在我的情况下,基于Web的请求)进行比较的人们来说,这种解决方案的数量是不必要的。

–杰夫·普茨(Jeff Putz)
09年6月17日在21:33

真好显然,有人需要给DateTime类一些扩展方法以四舍五入到最接近的值,以便可以重新使用这种良好的编码类型。

–chris.w.mclean
09年6月17日在21:48

这是不太可能的,但是当ticks = 0时这种方法不会中断吗?

–淘汰赛
13年7月24日在13:12

@adotout,如果timeSpan参数为零,则上面的Truncate方法将引发DivideByZeroException,这是您的意思是“当滴答= 0时方法中断”吗?当timeSpan为零时,最好抛出ArgumentException。

–乔
13年7月24日在19:46

您是否应该真正忽略DateTime.MinValue和DataTime.MaxValue?如果有人明确使用DateTime.MaxValue.Truncate(TimeSpan.FromSeconds(1)),我希望它能完成锡盒上的说明。

– Alex
11月2日9:41

#2 楼

var date = DateTime.Now;

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


评论


简洁明了,只需记住在构造函数的末尾添加“,date.Kind”,以确保您不会丢失重要的信息。

– JMcDaniel
2011年2月2日在15:59

对性能敏感代码中的此解决方案要谨慎。我的应用在System.DateTime.GetDatePart中花费了12%的CPU时间。

–上校恐慌
16-10-25在8:43

这很简单,但是比标记为最佳答案的问题要慢。并不是说这可能是瓶颈,但是它慢了大约7-8倍。

–乔纳斯(Jonas)
17年8月3日在23:33



“慢得多”的陈述并不正确,取决于运行时间,其差异在50%到100%之间。净4.7.2:0.35µs和0.62µs,核心3.1:0.18µs和0.12µs,即微秒(10 ^ -6秒)

– juwens
2月3日15:55

#3 楼

这是基于先前答案的扩展方法,可让您截断为任何分辨率...

用法:

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


评论


这是一个真正灵活且可重复使用的解决方案,简洁明了,不会太冗长。我的投票是最好的解决方案。

–Jaans
15年9月17日在11:21

您实际上不需要%操作数周围的括号。

– ErikE
16 Dec 9'在3:29

..但我认为这些括号增加了清晰度。

– Orion elenzil
17年5月27日下午5:21

#4 楼

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


评论


-1:仅在DateTime值不包含毫秒的分数时才有效。

–乔
09年6月17日在10:43

使用此方法导致我的某些单元测试失败:预期:2010-05-05 15:55:49.000但是是:2010-05-05 15:55:49.000。我猜是由于乔提到的关于毫秒的分数。

–塞斯·里诺(Seth Reno)
2010年5月5日20:57



不适用于序列化,例如2010-12-08T11:20:03.000099 + 15:00是输出,不能完全砍掉毫秒。

– joedotnot
2010-12-8在0:24



毫秒属性提供0到999(含)之间的整数。因此,如果手术前一天的时间是23:48:49.1234567,那么该整数将是123,手术后一天的时间是23:48:49.0004567。因此,它还没有被截断到整秒。

–杰普·斯蒂格·尼尔森(Jeppe Stig Nielsen)
13年8月24日在12:43



#5 楼

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

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


#6 楼

为什么不比较毫秒而不是比较毫秒?

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




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


评论


第一个选项不起作用,因为TotalSeconds是双精度型;它还返回毫秒。

– Jowen
2010-6-10 10:21

比较差异不会得到截断然后比较的结果。例如。 5.900和6.100相距不到一秒,因此可以与您的方法进行比较。但是截断的值5和6不同。哪个合适取决于您的要求。

–乔
15年1月29日在11:46

#7 楼

不太明显,但快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之间的某个刻度)将保留。

– net
2012年9月12日于20:59

#8 楼

四舍五入到第二个:

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

评论


这是否与7年前最受好评并发布的答案相同?

– Alex
11月2日,11:51



#9 楼

易于阅读的方法是...

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


评论


就性能而言,转换为字符串并进行解析是一个糟糕的主意。

–杰夫·普茨(Jeff Putz)
2015年9月10日下午12:31

@JeffPutz是的,但这很简单。适用于自动测试,在该测试中,从数据库插入和拉出的值丢失滴答声(我的确切情况)。但是,这个答案可能比实际要简单,因为var now = DateTime.Parse(DateTime.Now.ToString())可以正常工作。

–格林枪杀案
17年8月16日在9:32

@GrimmTheOpiner-大多数情况下,“ ...效果很好”,但不能保证。它的作用是:“将DateTime的值四舍五入为当前用户“控制面板”首选项中所配置的精度“ Long time”。通常,但不一定是秒。

–乔
18-09-6在20:07



就像它的简单一样,性能对于自动测试情况也不是问题。

– liang
19年8月21日在9:13

#10 楼

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

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


#11 楼

关于Diadistis反应。这对我有用,除了在乘法之前必须使用Floor删除除法的小数部分。因此,

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


成为

d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);


我期望两个Long值的除法结果a Long,因此删除了小数部分,但将其解析为Double,然后在乘法后留下了完全相同的值。

Eppsy

#12 楼

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


#13 楼

这是我在此处发布的扩展方法版本,并且存在类似问题。这以一种易于阅读的方式验证了ticks值,并保留了原始DateTime实例的DateTimeKind。 (当存储到像MongoDB这样的数据库时,这具有微妙但相关的副作用。)如果我的真实目标是将DateTime截断为指定值(例如Hours / Minutes / Seconds / MS),则建议而是在您的代码中实现此扩展方法。它确保您只能截断到一个有效的精度,并且保留原始实例的重要DateTimeKind元数据: br />
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.");
}


#14 楼

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

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


并通过使用

ToLongDateString() // its show 19 February 2016.


:P

评论


-1。我可以看到问题可能被误解为要求生成字符串而不是DateTime,但这完全忽略了输出中的时间分量。 (这也使得不必访问Today属性。)

–培根
19-10-30在1:06

#15 楼

新方法

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


//定义字符串传递参数dd-mmm-yyyy返回2016年2月24日

或在文本框上显示
/>
txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy");


//放在PageonLoad上

评论


-1。我可以看到问题可能被误解为要求生成字符串而不是DateTime,但这完全忽略了输出中的时间分量。 (这也使得不必访问Today属性。)

–培根
19-10-30在1:06

#16 楼

就我而言,我的目标是从datetimePicker工具中保存TimeSpan而不保存秒和毫秒,这是解决方案。 HH:mm”,然后将其转换回TimeSpan。

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


评论


更好的方法(意图更清晰,避免格式化为字符串并从字符串进行解析)是DateTime datetime = datetimepicker1.Value;。 TimeSpan timeSpan =新的TimeSpan(datetime.Hour,datetime.Minute,0);或者,您可以使用对TimeSpan值进行运算的Joe扩展方法的一种变体,并使用TimeSpan timeSpan = datetime.TimeOfDay.Truncate(TimeSpan.FromSeconds(1));缩短秒数。

–培根
19-10-30在1:26



#17 楼

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

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


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

评论


这是不理想的。然后,您有一个字符串,而不是DateTime。

–杰夫·普茨(Jeff Putz)
19-10-10在14:19