tags:

views:

477

answers:

4

In my c# app, I pass a string variable that is of format yyyymmdd-yyyymmdd that represents a from and to date. I want to get the start and end times for these dates respectively. Currently I have the below code but was wondering if there was more of an elegant solution?

So for pdr = 20090521-20090523 would get "20090521 00:00:00" and "20090523 23:59:59"

private void ValidateDatePeriod(string pdr, out DateTime startDate, 
                                out DateTime endDate)
{
    string[] dates = pdr.Split('-');

    if (dates.Length != 2)
    {
        throw new Exception("Date period is of incorrect format");
    }

    if (dates[0].Length != 8 || dates[1].Length != 8)
    {
        throw new Exception("Split date periods are of incorrect format");
    }

    startDate = DateTime.ParseExact(dates[0] + " 00:00:00", 
        "yyyyMMdd HH:mm:ss", null);
    endDate = DateTime.ParseExact(dates[1] + "23:59:59", 
        "yyyyMMdd HH::mm:ss", null);
}
+2  A: 

The DateTime object has a property called Date which will return just the date portion. (The time portion is defaulted to 12:00 am).

I would recommend as a more elegant solution (IMHO) that if you want to allow any datetime on the last day, then you add 1 day to the date, and compare to allow times greater than or equal to the start date, but strictly less than the end date (plus 1 day).

// Calling code.  beginDateTime and endDateTime are already set.
// beginDateTime and endDateTime are inclusive.
// targetDateTime is the date you want to check.
beginDateTime = beginDateTime.Date;
endDateTime = endDateTime.Date.AddDays(1);

if ( beginDateTime <= targetDateTime &&
     targetDateTime < endDateTime )
   // Do something.
Matt Brunell
i was wanting to return 2 datetimes from parsing a string, so the calling method could then use these dates to query my db.
David Liddle
@Matt: your advice is particularly sound if times can have a sub-second resolution.
Jonathan Leffler
+2  A: 

That's pretty much what I would do, with some small tweaks (really no big deal, just nitpicking):

  • The TryParse()/TryParseExact() methods should be used which return false instead of throwing exceptions.
  • FormatException is more specific than Exception
  • No need to check for Length == 8, because ParseExact()/TryParseExact() will do this
  • "00:00:00" and "23:59:59" are not needed
  • return true/false is you were able to parse, instead of throwing an exception (remember to check value returned from this method!)

Code:

private bool ValidateDatePeriod(string pdr, out DateTime startDate, 
         out DateTime endDate)
{
   string[] dates = pdr.Split('-');

   if (dates.Length != 2)
   {
       return false;
   }

   // no need to check for Length == 8 because the following will do it anyway
   // no need for "00:00:00" or "23:59:59" either, I prefer AddDays(1)

   if(!DateTime.TryParseExact(dates[0], "yyyyMMdd", null, DateTimeStyles.None, out startDate))
      return false;

   if(!DateTime.TryParseExact(dates[1], "yyyyMMdd", null, DateTimeStyles.None, out endDate))
      return false;

   endDate = endDate.AddDays(1);
   return true;
}
Lucas
thanks for the comments. good to know i was on the right track and grateful for the tweaks
David Liddle
+2  A: 
startDate = DateTime.ParseExact(dates[0], "yyyyMMdd");
endDate = DateTime.ParseExact(dates[1], "yyyyMMdd").AddDays(1).AddSeconds(-1);

You really don't need to concatenate extra values onto the string for the time portion.

Tracker1
A: 

You could define two extension methods somewhere, in a utility class like so :

public static DateTime EndOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 23, 59, 59, 999);
}

public static DateTime StartOfDay(this DateTime date)
{
    return new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
}

And then use them in code like so :

public DoSomething()
{
    DateTime endOfThisDay = DateTime.Now.EndOfDay();
}
Andrei Rinea