tags:

views:

2889

answers:

8

I'm trying to compare a time stamp from an incoming request to a database stored value. SQL Server of course keeps some precision of milliseconds on the time, and when read into a .NET DateTime, it includes those milliseconds. The incoming request to the system, however, does not offer that precision, so I need to simply drop the milliseconds.

I feel like I'm missing something obvious, but I haven't found an elegant way to do it (C#).

+21  A: 
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
chris.w.mclean
Very elegant. Should've thought of that! Well done.
Jeff Putz
+1, I do this a lot in SQL to get the first day of the month. A ton faster than going to string and back.
Josh Einstein
-1: Will work only if the DateTime value does not include fractions of a millisecond.
Joe
Using this method caused some of my unit tests to fail:Expected: 2010-05-05 15:55:49.000But was: 2010-05-05 15:55:49.000.I'm guessing due to what Joe mentioned about fractions of a millisecond.
Seth Reno
+5  A: 
date = DateTime.Now;

date = new DateTime(date.Year,date.Month,date.Day,date.Hour,date.Minute,date.Second)
benPearce
i was about to paste a solution like this... imo this is the most straightforward approach(not sure why this only has a few votes)
Venkat D.
the best way to go..
andrew007
+3  A: 

Instead of dropping the milliseconds then comparing, why not compare the difference?

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

or

TimeSpan precision = TimeSpan.FromSeconds(1);
bool areEqual = (x-y).Duration() < precision;
Bob
the first option doesnt work, because TotalSeconds is a double; it also returns the milliseconds.
Jo-wen
+4  A: 

Less obvious but more than 2 times faster :

// 10000000 runs

DateTime d = DateTime.Now;

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

// 1296,875ms
d = d.AddMilliseconds(-d.Millisecond);
Diadistis
+19  A: 

The following will work for a DateTime that has fractional milliseconds, and also preserves the Kind property (Local, Utc or Undefined).

DateTime dateTime = ... anything ...
dateTime = new DateTime(
    dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond), 
    dateTime.Kind
    );
Joe
+1: Preserving the Kind property.
Richard
While I'll give you this because you're technically correct, for people reading data out of SQL Server to compare to some distributed data (a Web-based request, in my case), this amount of resolution is not necessary.
Jeff Putz
Nice. Clearly someone needs to give the DateTime class some extension methods to round to nearest whatever so that this type of good coding will get reused.
chris.w.mclean
+1 for truncating fractions of a millisecond
Seth Reno
A: 

Regarding Diadistis response. This worked for me, except I had to use Floor to remove the fractional part of the division before the multiplication. So,

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

becomes

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

I would have expected the division of two Long values to result in a Long, thus removing the decimal part, but it resolves it as a Double leaving the exact same value after the multiplication.

Eppsy

+2  A: 

Here is an extension method based on a previous answer that will let you truncate to any resolution...

Usage:

DateTime myDateSansMilliseconds = myDate.Truncate(TimeSpan.TicksPerSecond);
DateTime myDateSansSeconds = myDate.Truncate(TimeSpan.TicksPerMinute)

Class:

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);
    }
}
Sky Sanders
A: 
DateTime dateTime = Convert.ToDateTime(DateTime.Now.ToShortTimeString());
accidentalgenius