How to truncate milliseconds off of a .NET DateTime

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

18 Answers

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
var date = DateTime.Now; date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind); 
5

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
DateTime d = DateTime.Now; d = d.AddMilliseconds(-d.Millisecond); 
4

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

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

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

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

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) 

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

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

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

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

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

You can simply use Split

 new TimeSpan(new DateTime(1970, 1, 1).Ticks).TotalSeconds.ToString().Split('.')[0] 
1

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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like