views:

183

answers:

4
+2  Q: 

Just Date or Time

I'm just wondering ..

I have and object like this

public class Entry{

public DateTime? Date { get; set;} // This is just Date

public DateTime? StartTime { get; set; } //This is just Time

public TimeSpan Duration { get; set; } //Time spent on entry

}

Is there a more appropriate type than DateTime or better strategy to handling just Time and Date? Without the pain of having to add a DateTime.MinDate() to all my Start and End Times?

--- update ---

1 - I like to be able to request if Date or StartTime is Null seperartly on the Entry object.

2 - Entry should allow the user to input Duration without indication of date. Even a default date like DateTime.MinDate() seems like a poor design. (This is why i choose TimeSpan not Start and EndTime)

+6  A: 

You could use a TimeSpan for your StartTime and EndTime properties. That's what the DateTime.TimeOfDay property returns.

There's also the DateTime.Date property which returns a DateTime with the time element set to midnight.

Having said that, I would probably recommend ditching your Date property altogether and storing full DateTimes (ie, date and time) in your StartTime and EndTime properties.

LukeH
I would suggest the same thing. You don't need the Date property. Just have the StartTime and EndTime contain the date info.
Meta-Knight
@Meta-Knight; in this particular case ,, the use case allows the user only to input Timespent without indication of the date or time. Which then in a later use-case is added, but not always.
BBorg
@Luke Problem with ditching Date altogether is, I will unable to check if Time was set or not. Since 00:00:00 is also a valid starttime
BBorg
@BBorg: Is your object actually in a useful state when the date or time is null, or do you just need to know for validation purposes etc in the UI?
LukeH
@Luke the state is valid. Gaffa seems to have nailed the issue.
BBorg
+1  A: 

You're far better off leaving your references as DateTimes. If you only store the time, then you have issues when your Entry spans more than a 24-hour period. Store them as DateTimes as you have them now, and apply whatever formatting is necessary to represent just the time portion to your end-user.

Adam Robinson
yeah chrisF also pointed out this weakness in my example:-)
BBorg
+5  A: 

Don't split up the date and time components where you store the data. You can provide properties to extract those if you like:

public class Entry {

   public DateTime StartPoint { get; set; }
   public TimeSpan Duration { get; set; }

   public DateTime StartDate { get { return StartPoint.Date; } }
   public TimeSpan StartTime { get { return StartPoint.TimeOfDay; } }
   public DateTime EndPoint { get { return StartPoint + Duration; } }
   public DateTime EndDate { get { return EndPoint.Date; } }
   public TimeSpan EndTime { get { return EndPoint.TimeOfDay; } }

}

Update:
If you want to have null values for date and time, you can add properties for that without having to split the date and time:

public class Entry{

   private DateTime _startPoint;

   public bool HasStartDate { get; private set; }
   public bool HasStartTime { get; private set; }
   public TimeSpan Duration { get; private set; }

   private void EnsureStartDate() {
      if (!HasStartDate) throw new ApplicationException("Start date is null.");
   }

   private void EnsureStartTime() {
      if (!HasStartTime) throw new ApplicationException("Start time is null.");
   }

   public DateTime StartPoint { get {
      EnsureStartDate();
      EnsureStartTime();
      return _startPoint;
   } }

   public DateTime StartDate { get {
      EnsureStartDate();
      return _startPoint.Date;
   } }

   public TimeSpan StartTime { get {
      EnsureStartTime();
      return _startPoint.TimeOfDay;
   } }

   public DateTime EndPoint { get { return StartPoint + Duration; } }

   public DateTime EndDate { get { return EndPoint.Date; } }

   public TimeSpan EndTime { get { return EndPoint.TimeOfDay; } }

   public Entry(DateTime startPoint, TimeSpan duration)
     : this (startPoint, true, true, duration) {}

   public Entry(TimeSpan duration)
     : this(DateTime.MinValue, false, false, duration) {}

   public Entry(DateTime startPoint, bool hasStartDate, bool hasStartTime, TimeSpan duration) {
      _startPoint = startPoint;
      HasStartDate = hasStartDate;
      HasStartTime = hasStartTime;
      Duration = duration;
   }

}
Guffa
@Guffa I dont see how i could easily check if Date and Time are null seperately?
BBorg
@BBorg: As you added that requirement after I answered, I added an update above.
Guffa
@Guffa,, nice, I'm gonna test this a bit but i do think this will work well, TY
BBorg
A: 

I'd like to compliment Guffa's answer with two more best practices:

  1. Store all of your dates as UTC in the database.
  2. Avoid System.DateTime and favor System.DateTimeOffset.
    1. SQL Server 2008’s datetimeoffset type is the equivalent of DateTimeOffset.
Jim G.
@Jim G - Im happy about the answers also .. but I fail to see how i would easily check if Date was set or not (Date != null) seperatly from time (Time != null) if i merge to two properties?
BBorg