DateTime difference in days on the basis of Date only - c#

I need to find the difference in days between two dates.
For example:
Input: **startDate** = 12-31-2012 23hr:59mn:00sec, **endDate** = 01-01-2013 00hr:15mn:00sec
Expected output: 1
I tried the following:
(dt1-dt2).TotalDays and convert to integer but didn't give me appropriate answer as double has to be converted to int - tried Math.Ceiling, Convert.To...
dt1.day - dt2.day does not work across months
dt.Substract() has the same output as option 1 mentioned above.
None of the above worked, so I ended up writing the following code. The code works well, but I feel that there must be a solution with only a couple of lines of code.
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
//Initializing with 0 as default return value
int difference = 0;
//If either of the dates are not set then return 0 instead of throwing an exception
if (startDate == default(DateTime) | endDate == default(DateTime))
return difference;
//If the dates are same then return 0
if (startDate.ToShortDateString() == endDate.ToShortDateString())
return difference;
//startDate moving towards endDate either with increment or decrement
while (startDate.AddDays(difference).ToShortDateString() != endDate.ToShortDateString())
{
difference = (startDate < endDate) ? ++difference : --difference;
}
return difference;
}
Note: I do not have any performance issue in the while-loop iteration as the max difference will not be more than 30 to 45 days.

Well, it sounds like you want the difference in the number of days, ignoring the time component. A DateTime with the time component reset to 00:00:00 is what the Date property gives you:
(startDate.Date - endDate.Date).TotalDays

If you use the DateTime.Date property this will eliminate the time
date1.Date.Subtract(date2.Date).Days

Use TimeStamp. Just subtract two dates (using DateTime.Date property), get the difference in time span and return TotalDays
TimeSpan ts = endDate.Date - startDate.Date;
double TotalDays = ts.TotalDays;
So your extension method can be as simple as:
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
return (int) (endDate.Date - startDate.Date).TotalDays;
// to return just a int part of the Total days, you may round it according to your requirement
}
EDIT: Since the question has been edited, you may check the following example.
Consider the following two dates.
DateTime startDate = new DateTime(2012, 12, 31, 23, 59, 00);
DateTime endDate = new DateTime(2013, 01, 01, 00, 15, 00);
You can write the extension method as:
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
TimeSpan ts = endDate - startDate;
int totalDays = (int) Math.Ceiling(ts.TotalDays);
if (ts.TotalDays < 1 && ts.TotalDays > 0)
totalDays = 1;
else
totalDays = (int) (ts.TotalDays);
return totalDays;
}
For the above dates it will give you 1

Related

How to remove the portion other than date and time from datetime object? [duplicate]

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#).
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
if (dateTime == DateTime.MinValue || dateTime == 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
...
var date = DateTime.Now;
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
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);
}
}
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
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;
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.
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);
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.
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);
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
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
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
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;
You can simply use Split
new TimeSpan(new DateTime(1970, 1, 1).Ticks).TotalSeconds.ToString().Split('.')[0]
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.

How to get dates between two dates in C#

I would like to get dates between two dates. Instead of expected 9 different dates, I get 875287 and run out of memory. What would be the problem with the code below?
StartDate value is 01/04/2016 00:00:00
EndDate value is 10/04/2016 00:00:00
var selectedDates = new List<DateTime?>();
for (var date = StartDate; date <= EndDate; date.Value.AddDays(1))
{
selectedDates.Add(date);
}
You aren't assigning the value of date.Value.AddDays(1) to anything, so it ends up in an infinite loop. You'd need to change your code so that date is set to the result of AddDays.
for (var date = StartDate; date <= EndDate; date = date.AddDays(1))
{
selectedDates.Add(date);
}
LINQ solution (let's generate selectedDates):
var selectedDates = Enumerable
.Range(0, int.MaxValue)
.Select(index => new DateTime?(StartDate.AddDays(index)))
.TakeWhile(date => date <= EndDate)
.ToList();
As far as I can see, since AddDays method returns a new instance of a DateTime, it does not change the current instance since DateTime is immutable.
Looks like your date is DateTime?, you can change this part as;
for (var date = StartDate; date <= EndDate; date = date.Value.AddDays(1))
{
selectedDates.Add(date);
}
As usr pointed, this might be affected on DST. You might wanna check Dmitry's answer as well.
A shorter notation using Linq's Range method uses the ability to already figure out the number of days using the TimeSpan.Days property after subtracting start from end.
Assuming the start is before end you'd end up with:
DateTime StartDate = new DateTime(1979, 10, 4);
DateTime EndDate = new DateTime(2016, 10, 4);
var dates = Enumerable.Range(0, (EndDate - StartDate).Days + 1)
.Select(day => StartDate.AddDays(day))
If you need it to be Nullable, add:
.Cast<DateTime?>()
If you need this to be a List, add:
.ToList()
It's probably quite a bit more efficient than the other LINQ based solution.
Decided to change it up with a do/while
var selectedDates = new List<DateTime?>();
DateTime? StartDate = DateTime.Parse("01/04/2016 00:00:00");
DateTime? EndDate = DateTime.Parse("10/04/2016 00:00:00");
do
{
selectedDates.Add(StartDate);
StartDate = StartDate.Value.AddDays(1);
}while(StartDate < EndDate);

Have datetime.now return to the nearest second

I have a "requirement" to give a timestamp to the nearest second... but NOT more accurate than that. Rounding or truncating the time is fine.
I have come up with this abomination
dateTime = DateTime.Parse(DateTime.UtcNow.ToString("U"));
(U is the Long format date and time. "03 January 2007 17:25:30")
Is there some less horrific way of achieving this?
Edit: So from the linked truncate milliseconds answer (thanks John Odom) I am going to do this
private static DateTime GetCurrentDateTimeNoMilliseconds()
{
var currentTime = DateTime.UtcNow;
return new DateTime(currentTime.Ticks - (currentTime.Ticks % TimeSpan.TicksPerSecond), currentTime.Kind);
}
barely less horrific.. but it does preserve the 'kind' of datetime which I do care about. My solution did not.
You could implement this as an extension method that allows you to trim a given DateTime to a specified accuracy using the underlying Ticks:
public static DateTime Trim(this DateTime date, long ticks) {
return new DateTime(date.Ticks - (date.Ticks % ticks), date.Kind);
}
Then it is easy to trim your date to all kinds of accuracies like so:
DateTime now = DateTime.Now;
DateTime nowTrimmedToSeconds = now.Trim(TimeSpan.TicksPerSecond);
DateTime nowTrimmedToMinutes = now.Trim(TimeSpan.TicksPerMinute);
You can use this constructor:
public DateTime(
int year,
int month,
int day,
int hour,
int minute,
int second
)
so it would be:
DateTime dt = DateTime.Now;
DateTime secondsDt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
If you really want to round the time to the nearest second, you can use:
DateTime.MinValue
.AddSeconds(Math.Round((DateTime.Now - DateTime.MinValue).TotalSeconds));
However unless that extra half a second really makes a difference, you can just remove the millisecond portion:
DateTime.Now.AddTicks( -1 * (DateTime.Now.Ticks % TimeSpan.TicksPerSecond));
Try this
TimeSpan span= dateTime.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
After working with the selected solution I am satisfied that it works well. However the implementations of the extension methods posted here do not offer any validation to ensure the ticks value you pass in is a valid ticks value. They also do not preserve the DateTimeKind of the DateTime object being truncated. (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
Here is a rounding method that rounds up or down to the nearest second instead of just trimming:
public static DateTime Round(this DateTime date, long ticks = TimeSpan.TicksPerSecond) {
if (ticks>1)
{
var frac = date.Ticks % ticks;
if (frac != 0)
{
// Rounding is needed..
if (frac*2 >= ticks)
{
// round up
return new DateTime(date.Ticks + ticks - frac);
}
else
{
// round down
return new DateTime(date.Ticks - frac);
}
}
}
return date;
}
It can be used like this:
DateTime now = DateTime.Now;
DateTime nowTrimmedToSeconds = now.Round(TimeSpan.TicksPerSecond);
DateTime nowTrimmedToMinutes = now.Round(TimeSpan.TicksPerMinute);

Iterate over each Day between StartDate and EndDate [duplicate]

This question already has answers here:
How do I loop through a date range?
(17 answers)
Closed 6 years ago.
I have a DateTime StartDate and EndDate.
How can I, irrespective of times, iterate across each Day between those two?
Example: StartDate is 7/20/2010 5:10:32 PM and EndDate is 7/29/2010
1:59:12 AM.
I want to be able to iterate across 7/20, 7/21, 7/22 .. 7/29.
for(DateTime date = StartDate; date.Date <= EndDate.Date; date = date.AddDays(1))
{
...
}
The .Date is to make sure you have that last day, like in the example.
An alternative method that might be more reusable is to write an extension method on DateTime and return an IEnumerable.
For example, you can define a class:
public static class MyExtensions
{
public static IEnumerable EachDay(this DateTime start, DateTime end)
{
// Remove time info from start date (we only care about day).
DateTime currentDay = new DateTime(start.Year, start.Month, start.Day);
while (currentDay <= end)
{
yield return currentDay;
currentDay = currentDay.AddDays(1);
}
}
}
Now in the calling code you can do the following:
DateTime start = DateTime.Now;
DateTime end = start.AddDays(20);
foreach (var day in start.EachDay(end))
{
...
}
Another advantage to this approach is that it makes it trivial to add EachWeek, EachMonth etc. These will then all be accessible on DateTime.
You have to be careful about end-date. For example, in
Example: StartDate is 7/20/2010 5:10:32 PM and EndDate is 7/29/2010 1:59:12 AM.
I want to be able to iterate across 7/20, 7/21, 7/22 .. 7/29.
date < endDate will not include 7/29 ever. When you add 1 day to 7/28 5:10 PM - it becomes 7/29 5:10 PM which is higher than 7/29 2 AM.
If that is not what you want then I'd say you do
for (DateTime date = start.Date; date <= end.Date; date += TimeSpan.FromDays(1))
{
Console.WriteLine(date.ToString());
}
or something to that effect.
The loops of #Yuriy Faktorovich, #healsjnr and #mho will all throw a System.ArgumentOutOfRangeException: The added or subtracted value results in an un-representable DateTime
exception if EndDate == DateTime.MaxValue.
To prevent this, add an extra check at the end of the loop
for(DateTime date = StartDate; date.Date <= EndDate.Date; date = date.AddDays(1))
{
...
if (date.Date == DateTime.MaxValue.Date)
{
break;
}
}
(I would have posted this as a comment to #Yuriy Faktorovich's answer, but I lack reputation)
DateTime date = DateTime.Now;
DateTime endDate = date.AddDays(10);
while (date < endDate)
{
Console.WriteLine(date);
date = date.AddDays(1);
}

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#).
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
if (dateTime == DateTime.MinValue || dateTime == 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
...
var date = DateTime.Now;
date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
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);
}
}
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);
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;
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.
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);
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.
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);
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
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
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
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;
You can simply use Split
new TimeSpan(new DateTime(1970, 1, 1).Ticks).TotalSeconds.ToString().Split('.')[0]
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.

Categories