-2

There are three styles of Date and Time that can go into a DateTime variable; DateTime, Date or Time. I would like to differentiate between them. How can I do so?

I am creating column filtering on a DataGrid. Depending if it is one of the three the filter will display a DateTime picker or a DatePicker or a Time picker.

Hank
  • 2,456
  • 3
  • 35
  • 83
  • Differentiate in what sense? If you just want the date part, use `.Date`. If you want just the time part, use `.TimeOfDay`. Other than that, there is no differentiation. – Mrchief Aug 29 '14 at 03:43
  • I am creating column filtering on a DataGrid. Depending if it is one of the three the filter will display a DateTime picker or a DatePicker or a Time picker. – Hank Aug 29 '14 at 03:48
  • You need to know what is stored in `DateTime` variable. There is no reasonable 100% reliable way to guess. Is "0-0-0 1:00" is just time or first our of year 0? – Alexei Levenkov Aug 29 '14 at 04:04
  • 1
    My way of thinking: If its not provided by the framework, create it yourself. Create a couple of `struct`s for `Date` and `Time`.. and then set data to these `struct`s from a specific `DateTime`. Also create a couple of extension methods for DateTime that can help you get Date or Time out of a DateTime. – Aniket Inge Aug 29 '14 at 04:17
  • Kind of like a sub-type of DateTime? – Hank Aug 29 '14 at 04:18
  • 1
    `DateTime` is a `value type` and cannot be inherited from(extended). You can create a simple PCC(pure C# class or struct) – Aniket Inge Aug 29 '14 at 04:20

3 Answers3

1

The only way to check if DateTime has a date value is to make it a nullable type.

So something like this:

DateTime? dt;

if(dt.HasValue) {
 //has date
 if(dt.Value.TimeOfDay.TotalSeconds == 0) {
   // display datepicker
 } else {
   // display timepicker
 }
} else {

// show date time picker
}

Other than that, a regular DateTime will always have a date value (if not time value, or both). That is because it's a struct, hence it is not nullable unless you "make" it so (by wrapping in Nullable, which is done either manually (Nullable<DateTime>) or much simpler - by appending ? to the type (DateTime?) as demonstrated above).

If you have an option to go with different datatype (other than DateTime), then I suggest looking at NodaTime (Microsoft should simply build this into CLR and drop their lame DateTime struct).

You can then have 3 nullable properties

LocalDate? Date;
LocalDateTime? DateTime;
LocalTime? Time;

So based on which prop has value, you show the appropriate control. Of course, you also need to set the appropriate property which I'm not sure if you have any control on.

Mrchief
  • 75,126
  • 20
  • 142
  • 189
1

This classification is not part of the struct. IOW there's no built-in way to do this, so it's up to you to pick the implementation you'd like.

It has been suggested to check if the TotalSeconds == 0, which may satisfy you, imo it's a wonderful solution, but I think it should be used with caution because it is limited. Because what if you want to have a time+date that points to the date when TotalSeconds that really is == 0. This approach will turn this into just a date automatically.

I suggest that if you do not associate this time with a date, choose TimeSpan and make your life so much easier. However I assume this is not the case.

So, if the time really is associated with a date, I suggest you simply make your own type that wraps a DateTime, plus a boolean flag that will answer your question: is it just a date or date+time?.
This is obvious but I simply must say this anyways: if you do take this approach - encapsulate & hide!
If you expose DateTime as a field, an end-user might change the time of a date, expecting it to become date+time, yet the flag will not follow along. So don't just make a wrapper, make your own type that just uses DateTime internally.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90
  • Creating new types will definitely be more definitive, for others I found the following struct for a Date type and using this with a little modification can also create a similar Time type: https://github.com/claycephas/csharp-date/blob/master/CSharpDate/Date.cs – Hank Aug 29 '14 at 05:45
1

There is no absolute way to differentiate. A DateTime always has a date portion and a time portion. If you create a DateTime from just a date then the time portion will be zeroed to midnight, but there is no difference between that and a value that actually represents the stroke of midnight on that date. If you create a DateTime from just a time then the date portion will be equal to #1/01/0001#, but there's no difference between that and a value that actually represents a time on the first day of the new era.

One option is to assume that a DateTime with a non-zero time and a date of #1/01/0001# represents just a time and a value with a zeroed time portion represents just a date. With that in mind, you could add this extension:

public enum DateTimeType
{
    Date,
    Time,
    DateAndTime
}

public static class DateTimeExtensions
{
    private static readonly DateTime ZeroDate = new DateTime(1, 1, 1);

    public static DateTimeType GetDateTimeType(this DateTime value)
    {
        if (value.TimeOfDay == TimeSpan.Zero)
        {
            return DateTimeType.Date;
        }

        if (value.Date == ZeroDate)
        {
            return DateTimeType.Time;
        }

        return DateTimeType.DateAndTime;
    }
}
jmcilhinney
  • 50,448
  • 5
  • 26
  • 46