tags:

views:

386

answers:

5

I am using a System.DateTime object to allow a user to select a date range. The user is only able to select a date (not time) using a third party calendar so I will need to automatically specify the time of day it should use (ie: 00:00:00 or 23:59:59) after the date is chosen.

How can I specify the time after the date is already stored as a DateTime object by the calendar selector? I could use the AddHours, AddMinutes, AddSeconds methods but those are relative to the current time which may not be 00:00:00.

The startDate will need to have a time of 00:00:00 and endDate have a time of 23:59:59 to account for the entire days.

+8  A: 

If you already have a DateTime object created and want to replace the time with the 11:59:59PM for that given date, then you can use the .Date property to get the date with time set to 00:00:00 and then add the hours, minutes and seconds. For example:

var dt = yourDateInstance.Date.AddHours(23).AddMinutes(59).AddSeconds(59);

If by latest time, you mean 11:59:59 PM, then this should also work:

var dt = new DateTime(Now.Year, Now.Month, Now.Day, 23, 59, 59);
Jose Basilio
Indeed. There's nothing that says that you have to use Now.XXX to generate a year, month, day, hour, minute, or second. You can make a DateTime that represents any given instance of time.
Thomas Owens
What if I'm not entirely sure if its already set to 00:00:00? Can I directly set it to a time instead of it being relative?
Joe Philllips
Yes, the property .Date returns the date component with time set to 00:00:00. That's why the code says: youDateInstance.Date before adding the hours.
Jose Basilio
Very good! Thanks for the explanation. You may want to add that to your answer for us newbs who might not notice it.
Joe Philllips
@d03boy - ditto!
Jose Basilio
+8  A: 

To get the last instant for today:

DateTime d = new DateTime(Now.Year, Now.Month, Now.Day);
d = d.AddDays(1);
d = d.AddTicks(-1);


In response to your edit, here's what I would do:

DateTime start = new DateTime(Now.Year, Now.Month, Now.Day);
DateTime end = start.AddDays(1).AddTicks(-1);

// Or - just use end = start.AddDays(1), and use a < for comparison
Jon B
+1. I was thinking the same exact thing. Do you all have some sort of special keyboard with SO-intellisense/auto-complete built in?
Erich Mirabal
AddDays(1) will set it to 00:00:00 on the next day then?
Joe Philllips
@d03boy: exactly. AddDays() will be exactly 24 hours later. In this case, at 00:00:00.0. If you want the very instant before that, subtract one tick.
Jon B
This is assuming time is already set to 00:00:00 which may not be a safe assumption here. Can you directly set the time somehow?
Joe Philllips
@d03boyJon B instanciated a DateTime by specifying the year, month and day. That sets the time to 0 so there is not need to do add .Date before adding a day in this case.
Meta-Knight
@d03boy: From http://msdn.microsoft.com/en-us/library/xcfzdy4x.aspx : "The time of day for the resulting DateTime is midnight (00:00:00). The Kind property is initialized to DateTimeKind..::.Unspecified."
R. Bemrose
@d03boy: When you create a new DateTime and don't specify the time, it is 00:00:00. If you want to specify it anyway, just use new DateTime(Now.Year, Now.Month, Now.Day, 0, 0, 0);
Jon B
Thanks for the answer. Nice trick.
Joe Philllips
+2  A: 

DateTime d = DateTime.Today.AddDays(1).AddTicks(-1);

Peter Drier
+2  A: 
DateTime startDate = DateTime.Today;
DateTime stopDate = startDate.AddDays(1).AddTicks(-1);

As a note, DateTime.Today returns (from MSDN)

A System.DateTime set to today's date, with the time component set to 00:00:00.

So as others have noted, add a day, then subtract the smallest time quantum (a tick), and you get the last possible time for the current day.

Of course, you might have to think about TimeZones and such depending where the code runs versus where the user is. UTC time might be good, but that might bump you off a day (either way) depending where your code runs.

Erich Mirabal
Glad your thinking of timezones. That has been taken care of.
Joe Philllips
+4  A: 

Your question has already been answered, but IMHO a better way is not to bother attempting to subtract a tick, a second, or whatever from the end of the range, and compare using strictly less than.

So that if you want all dates in an inclusive range from startDate to endDate, ignoring the time, you could use the following in C#:

if ((myDate >= startDate.Date) && (myDate < endDate.Date.AddDays(1)))
{
    // ... it's in the range
}

or in T-SQL, assuming your @StartDate and @EndDate are exactly midnight, something like:

WHERE SomeDate >= @StartDate AND SomeDate < DATEADD(d,1,@EndDate)

UPDATE

Updated example to show an inclusive range in response to comments.

Joe
IMO, endDate should still be included in the search. What if I choose June 2nd and June 2nd as my starting and end dates?
Joe Philllips
Then you could just add a day to endDate and use Joe's code ;-)
Meta-Knight