434

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

1
  • 5
    (3rd try...) Since 20% of the answers (1, 2, 3) describe how to omit or remove the milliseconds component from the formatted string representation of a DateTime, perhaps an edit is needed to make it clear that to "truncate"/"drop" milliseconds means "produce a DateTime value where all date/time components are the same except TimeOfDay.TotalMilliseconds is 0." People don't read, of course, but just to eliminate any ambiguity. Commented Oct 30, 2019 at 1:33

18 Answers 18

692

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

or the equivalent and shorter:

dateTime = dateTime.AddTicks( - (dateTime.Ticks % TimeSpan.TicksPerSecond));

This could be generalized into an extension method:

public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan)
{
    if (timeSpan == TimeSpan.Zero) return dateTime; // Or could throw an ArgumentException

    // Some comments suggest removing the following line.  I think the check
    // for MaxValue makes sense - it's often used to represent an indefinite expiry date.
    // (The check for DateTime.MinValue has no effect, because DateTime.MinValue % timeSpan
    // is equal to DateTime.MinValue for any non-zero value of timeSpan.  But I think
    // leaving the check in place makes the intent clearer).
    // YMMV and the fact that different people have different expectations is probably
    // part of the reason such a method doesn't exist in the Framework.
    if (dateTime == DateTime.MinValue || DateTime.MaxValue) return dateTime; // do not modify "guard" values

    return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks));
}

which is used as follows:

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
...
7
  • 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
    Commented Jun 17, 2009 at 21:33
  • 1
    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. Commented Jun 17, 2009 at 21:48
  • This is very unlikely, but doesn't this approach break when ticks = 0?
    – adotout
    Commented Jul 24, 2013 at 13:12
  • @adotout, the Truncate method above will throw a DivideByZeroException if the timeSpan parameter is zero, is this what you mean by "approach breaks when ticks = 0"? It would be better to throw an ArgumentException when timeSpan is zero.
    – Joe
    Commented Jul 24, 2013 at 19:46
  • 3
    Should you really ignore DateTime.MinValue and DataTime.MaxValue? If someone explicitly use DateTime.MaxValue.Truncate(TimeSpan.FromSeconds(1)) I'd expect that it does what is says on the tin.
    – Alex
    Commented Nov 2, 2020 at 9:41
194
var date = DateTime.Now;

date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
3
  • 13
    Be cautious about this solution in performance sensitive code. My app was spending 12% of CPU time in System.DateTime.GetDatePart. Commented Oct 25, 2016 at 8:43
  • 4
    It is simple, but slower than the question marked as best answer. Not that this may be a bottleneck, but it is approximately 7-8x slower.
    – Jonas
    Commented Aug 3, 2017 at 23:33
  • 3
    The "much slower" statements are not exaclty correct, the difference is between 50% and about 100% depending on the runtime; net 4.7.2: 0.35µs vs 0.62 µs and core 3.1: 0.18 µs vs 0.12 µs that's micro-seconds (10^-6 seconds)
    – juwens
    Commented Feb 3, 2020 at 15:55
99

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);
    }
}
3
  • 2
    This is a really flexible and re-usable solution, that is concise and expressive without being overly verbose. My vote as best solution.
    – Jaans
    Commented Sep 17, 2015 at 11:21
  • 2
    You don't actually need the parentheses around the % operands.
    – ErikE
    Commented Dec 9, 2016 at 3:29
  • 22
    .. but the parens add clarity, in my opinion. Commented May 27, 2017 at 5:21
39
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
4
  • 79
    -1: Will work only if the DateTime value does not include fractions of a millisecond.
    – Joe
    Commented Jun 17, 2009 at 10:43
  • 8
    Using this method caused some of my unit tests to fail: Expected: 2010-05-05 15:55:49.000 But was: 2010-05-05 15:55:49.000. I'm guessing due to what Joe mentioned about fractions of a millisecond.
    – Seth Reno
    Commented May 5, 2010 at 20:57
  • 6
    Doesn't work for serialization, e.g. 2010-12-08T11:20:03.000099+15:00 is the output, doesn't completely chop off the milliseconds.
    – joedotnot
    Commented Dec 8, 2010 at 0:24
  • 7
    The Millisecond property gives an integer between 0 and 999 (inclusive). So if the time of day before the operation was, say, 23:48:49.1234567, then that integer will be 123, and the time of day after the operation is 23:48:49.0004567. So it has not truncated to a whole number of seconds. Commented Aug 24, 2013 at 12:43
16

Sometimes you want to truncate to something calendar-based, like year or month. Here's an extension method that lets you choose any resolution.

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

To round down to the second:

dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)

Replace with TicksPerMinute to round down to the minute.


If your code is performance sensitive, be cautious about

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

My app was spending 12% of CPU time in System.DateTime.GetDatePart.

0
11

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;
2
  • 4
    the first option doesnt work, because TotalSeconds is a double; it also returns the milliseconds.
    – Jowen
    Commented Jun 10, 2010 at 10:21
  • 2
    Comparing the difference doesn't give the same result as truncating then comparing. E.g. 5.900 and 6.100 are less than a second apart, so would compare as equal with your method. But the truncated values 5 and 6 are different. Which is appropriate depends on your requirement.
    – Joe
    Commented Jan 29, 2015 at 11:46
8

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);
1
  • 3
    Note that the second option, d.AddMilliseconds(-d.Millisecond), does not necessarily move the DateTime exactly on to the previous, full second. d.Ticks % TimeSpan.TicksPerMillisecond ticks (somewhere between 0 and 9,999) beyond your second will remain.
    – Technetium
    Commented Sep 12, 2012 at 20:59
8

Not the fastest solution but simple and easy to understand:

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

A way for easy reading is...

//Remove milliseconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss", null);

And more...

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

I understand that it is easy to understand, but it lacks performance.

4
  • 8
    Converting to strings and parsing is an awful idea in terms of performance.
    – Jeff Putz
    Commented Sep 10, 2015 at 12:31
  • 3
    @JeffPutz true, but it is but simple. Suitable for an automated test where a value inserted and pulled from a DB loses the ticks (my exact situation). However this answer could be even simpler than it is, as var now = DateTime.Parse(DateTime.Now.ToString()) works just fine. Commented Aug 16, 2017 at 9:32
  • 1
    @GrimmTheOpiner - "...works just fine", mostly, but not guaranteed. What it does is: "Rounds a DateTime to whatever precision 'Long time' is configured as in the current user's Control Panel preferences". Which is usually, but not necessarily, seconds.
    – Joe
    Commented Sep 6, 2018 at 20:07
  • 2
    like its simplicity, performance is not an issue for automated testing situation.
    – liang
    Commented Aug 21, 2019 at 9:13
2

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

2 Extension methods for the solutions mentioned above

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

usage:

bool liesAfter = myObject.DateProperty.LiesAfterOrEqualsIgnoringMilliseconds(startDateTime, DateTimeKind.Utc);
0
2

This is my version of the extension methods posted here and in similar questions. This validates the ticks value in an easy to read way and preserves the DateTimeKind of the original DateTime instance. (This has subtle but relevant side effects when storing to a database like MongoDB.)

If the true goal is to truncate a DateTime to a specified value (i.e. Hours/Minutes/Seconds/MS) I recommend implementing this extension method in your code instead. It ensures that you can only truncate to a valid precision and it preserves the important DateTimeKind metadata of your original instance:

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

Then you can use the method like this:

DateTime dateTime = DateTime.UtcNow.Truncate(TimeSpan.TicksPerMillisecond);

dateTime.Kind => DateTimeKind.Utc
0
DateID.Text = DateTime.Today.ToShortDateString();

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

And By Use Of

ToLongDateString() // its show 19 February 2016.

:P

1
  • -1. I can see how the question might have been misinterpreted as asking to produce a string instead of a DateTime, but this omits time components from the output completely. (That makes accessing the Today property unnecessary, too.) Commented Oct 30, 2019 at 1:06
0

New Method

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

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

Or shown on textbox

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

// put on PageonLoad

1
  • 1
    -1. I can see how the question might have been misinterpreted as asking to produce a string instead of a DateTime, but this omits time components from the output completely. (That makes accessing the Today property unnecessary, too.) Commented Oct 30, 2019 at 1:06
0

In my case, I was aiming to save TimeSpan from datetimePicker tool without saving the seconds and the milliseconds, and here is the solution.

First convert the datetimePicker.value to your desired format, which mine is "HH:mm" then convert it back to TimeSpan.

var datetime = datetimepicker1.Value.ToString("HH:mm");
TimeSpan timeSpan = Convert.ToDateTime(datetime).TimeOfDay;
1
  • A better way (clearer intent, avoids formatting to and parsing back from a string) to do this would be DateTime datetime = datetimepicker1.Value; TimeSpan timeSpan = new TimeSpan(datetime.Hour, datetime.Minute, 0); Or you could use a variation of Joe's extension method that operates on TimeSpan values and use TimeSpan timeSpan = datetime.TimeOfDay.Truncate(TimeSpan.FromSeconds(1)); to truncate seconds. Commented Oct 30, 2019 at 1:26
0

You can simply use Split

 new TimeSpan(new DateTime(1970, 1, 1).Ticks).TotalSeconds.ToString().Split('.')[0]
1
  • Your answer could be improved by adding more information on what the code does and how it helps the OP.
    – Tyler2P
    Commented May 7, 2022 at 17:35
-2

I know the answer is quite late, but the best way to get rid of milliseconds is

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

Try printing the value of the variable, it will show the date time, without milliseconds.

1
  • 3
    This is not ideal. You've got a string then and not a DateTime.
    – Jeff Putz
    Commented Oct 10, 2019 at 14:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.