A type for Date only in C# - why is there no Date type?

后端 未结 13 1858
暗喜
暗喜 2020-11-28 10:23

In our C# project we have the need for representing a date without a time. I know of the existence of the DateTime, however, it incorporates a time of day as well. I

相关标签:
13条回答
  • 2020-11-28 10:45

    Allow me to speculate: Maybe it is because until SQL Server 2008 there was no Date datatype in SQL so it would be hard so store it in SQL server?? And it is after all a Microsoft Product?

    0 讨论(0)
  • 2020-11-28 10:47

    I've emailed refsrcfeedback@microsoft.com and that's their answer

    Marcos, this is not a good place to ask questions like these. Try http://stackoverflow.com Short answer is that you need a model to represent a point in time, and DateTime does that, it’s the most useful scenario in practice. The fact that humans use two concepts (date and time) to mark points in time is arbitrary and not useful to separate.

    Only decouple where it is warranted, don’t do things just for the sake of doing things blindly. Think of it this way: what problem do you have that is solved by splitting DateTime into Date and Time? And what problems will you get that you don’t have now? Hint: if you look at DateTime usages across the .NET framework: http://referencesource.microsoft.com/#mscorlib/system/datetime.cs#df6b1eba7461813b#references You will see that most are being returned from a method. If we didn’t have a single concept like DateTime, you would have to use out parameters or Tuples to return a pair of Date and Time.

    HTH, Kirill Osenkov

    In my email I'd questioned if it was because DateTime uses TimeZoneInfo to get the time of the machine - in Now propriety. So I'd say it's because "the business rules" are "too coupled", they confimed that to me.

    0 讨论(0)
  • 2020-11-28 10:47

    Because in order to know the date, you have to know the system time (in ticks), which includes the time - so why throw away that information?

    DateTime has a Date property if you don't care at all about the time.

    0 讨论(0)
  • 2020-11-28 10:51

    Allow me to add an update to this classic question:

    • Jon Skeet's Noda Time library is now quite mature, and has a date-only type called LocalDate. (Local in this case just means local to someone, not necessarily local to the computer where the code is running.)

    • A date-only type called Date is a proposed addition to the .NET Core, via the corefxlab project. You'll find it in the System.Time package, along with a TimeOfDay type, and several extension methods to the existing types.

    I've studied this problem significantly, so I'll also share several reasons for the necessity of these types:

    1. There is a logical discrepancy between a date-only, and a date-at-midnight value.

      • Not every local day has a midnight in every time zone. Example: Brazil's spring-forward daylight saving time transition moves the clock from 11:59:59 to 01:00:00.

      • A date-time always refers to a specific time within the day, while a date-only may refer to the beginning of the day, the end of the day, or the entire range of the day.

    2. Attaching a time to a date can lead to the date changing as the value is passed from one environment to another, if time zones are not watched very carefully. This commonly occurs in JavaScript (whose Date object is really a date+time), but can easily happen in .NET also, or in the serialization as data is passed between JavaScript and .NET.

    3. Serializing a DateTime with XML or JSON (and others) will always include the time, even if it's not important. This is very confusing, especially considering things like birth dates and anniversaries, where the time is irrelevant.

    4. Architecturally, DateTime is a DDD value-object, but it violates the Single Responsibly Principle in several ways:

      • It is designed as a date+time type, but often is used as date-only (ignoring the time), or time-of-day-only (ignoring the date). (TimeSpan is also often used for time-of-day, but that's another topic.)

      • The DateTimeKind value attached to the .Kind property splits the single type into three, The Unspecified kind is really the original intent of the structure, and should be used that way. The Utc kind aligns the value specifically with UTC, and the Local kind aligns the value with the environment's local time zone.

        The problem with having a separate flag for kind is that every time you consume a DateTime, you are supposed to check .Kind to decide what behavior to take. The framework methods all do this, but others often forget. This is truly a SRP violation, as the type now has two different reasons to change (the value, and the kind).

      • The two of these lead to API usages that compile, but are often nonsensical, or have strange edge cases caused by side effects. Consider:

        // nonsensical, caused by mixing types
        DateTime dt = DateTime.Today - TimeSpan.FromHours(3);  // when on today??
        
        // strange edge cases, caused by impact of Kind
        var london = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
        var paris = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");
        var dt = new DateTime(2016, 3, 27, 2, 0, 0);  // unspecified kind
        var delta = paris.GetUtcOffset(dt) - london.GetUtcOffset(dt);  // side effect!
        Console.WriteLine(delta.TotalHours); // 0, when should be 1 !!!
        

    In summary, while a DateTime can be used for a date-only, it should only do so when when every place that uses it is very careful to ignore the time, and is also very careful not to try to convert to and from UTC or other time zones.

    0 讨论(0)
  • 2020-11-28 10:55

    If you need to run date comparisons then use

    yourdatetime.Date;
    

    If you are displaying to the screen use

    yourdatetime.ToShortDateString();
    
    0 讨论(0)
  • 2020-11-28 10:55

    Why? We can only speculate and it doesn't do much to help solve engineering problems. A good guess is that DateTime contains all the functionality that such a struct would have.

    If it really matters to you, just wrap DateTime in your own immutable struct that only exposes the date (or look at the DateTime.Date property).

    0 讨论(0)
提交回复
热议问题