Skip to content

Proposal: System.Date type #14089

Description

@paulirwin

Currently, trying to use System.DateTime to represent just calendar dates is overkill and is an easy way to introduce bugs. SQL Server supports a native date-only type, and having a date-only type in .NET to match would be very handy. But not only from SQL: accepting an MVC action method parameter from an HTML5 input type="date" field would be simplified with a native Date type.

Examples:

Date d = new Date(2015, 2, 9);
Date d2 = Date.UtcToday;
Date d3 = Date.LocalToday;

// helper methods for adding/subtracting days, months, years, or TimeSpan
Date d4 = d.AddDays(7);
Date d5 = d.Subtract(TimeSpan.FromYears(2));

string s = d.ToString();
//--> "2015-02-09"

// properties:
int y = d.Year;
int m = d.Month;
int day = d.Day;
DayOfWeek weekday = d.DayOfWeek;
int doy = d.DayOfYear;

// convert from DateTime:
Date d6 = DateTime.UtcNow.ToDate();
Date d7 = (Date)DateTime.UtcNow;

// convert to DateTime:
DateTime dt = d.ToDateTime();
DateTime dt2 = (DateTime)d; // equivalent to new DateTime(d.Year, d.Month, d.Day)

Activity

  1. HaloFour commented on Feb 10, 2015

    @HaloFour

    Wouldn't it be more appropriate for Date.Add(TimeSpan) and Date.Subtract(TimeSpan) to return DateTime since TimeSpan contains a time portion?

    Beyond little details, though, I fully agree. There needs to be a type that conveys the concept of a date without time and vice versa. I actually like how Java 8 revamped their date/time libs so that date, time and zone are individual immutable components which can be combined into composite types representing DateTime, ZonedDateTime, etc.

  2. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    The idea is sound. In fact, you'll find a similar type called LocalDate in the Noda Time library that is designed exactly for this.

    There are a few general problems to consider though:

    • Date is a keyword in VB.Net, and it's already mapped to System.DateTime. Creating System.Date would confuse the heck out of VB programmers.
      • I suggest CalendarDate, as it describes exactly the purpose for the type - a date on a calendar.
    • Math with a Date and a TimeSpan wouldn't work cleanly. TimeSpan is a discrete unit of time (usually, elapsed time), with "tick" precision. Whole dates should work only with whole days or larger units. (Consider that not all calendar days are exactly 24 hours, due to the effects of daylight saving time.)
      • I suggest methods such as AddDays, AddMonths, and AddYears - but no interaction with TimeSpan.
    • One might also consider how System.Globalization.Calendar could play into this. Perhaps there is a constructor overload that takes a Calendar instance. The default would of course be GregorianCalendar.
      • This would solve a problem that DateTime has, in that it is always Gregorian internally. If you use a non-Gregorian calendar, that only works during formatting and parsing. (In other words, you can't actually represent a date on a non-Gregorian calendar with a DateTime presently)

    There are other related date/time deficiencies that could be addressed at the same time - (without borrowing all of the ideas of Noda Time):

    • .NET could use a TimeOfDay type. The current TimeSpan type is not ideal, as it can track negative time and times >= 24:00 - which just don't make sense for a time-of-day. Also, TimeSpan doesn't handle 12-hour meridem (am/pm).
      • This type would be a better fit for DateTime.TimeOfDay, and would align with SQL Server's time type. Though, I'm not sure how to go about remapping those in a backwards-compatible way.
    • .NET could also use a ZonedDateTime type, which would essentially combine DateTimeOffset with TimeZoneInfo. The goal would be a fully time-zone aware data type representing an instant in time with reference to a specific time zone.
      • However, one might argue that if you have need for such a type, you probably have need for the whole Noda Time library. :)
  3. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    @HaloFour - Regarding Date.Add(TimeSpan) == DateTime - That would be making the assertion that all days start at midnight - which is not true (again, due to DST). That is another problem DateTime has presently - DateTime.Today can actually return a DateTime with Local kind, that doesn't exist in the local time zone.

  4. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    Also - It might make sense to consider extracting all date/time related stuff to it's own Nuget package. (Microsoft.Bcl.Time perhaps?) I'm not sure if TimeSpan could go, given that it's used for elapsed-time measurement in many other areas - but probably DateTime, DateTimeOffset, TimeZoneInfo, *Calendar and whatever new types come out of this discussion could all go in there.

  5. michaelstaib commented on Feb 10, 2015

    @michaelstaib

    @mj1856 I wouldn't name it CalenderDate. I would prefer System.Date but for vb one could add an language alias that is named CalenderDate.

  6. michaelstaib commented on Feb 10, 2015

    @michaelstaib

    @HaloFour I also think Date.Add(TimeSpan) and Date.Subtract(TimeSpan) would be more consistent than Date.AddDays(int) but if there is an need for shortcuts so that you do not have to provide all the time a TimeSpan object there should be also a SubtractDays(int).

  7. tarekgh commented on Feb 10, 2015

    @tarekgh
    Member

    @michaelstaib I agree CalendarDate name will be confusing as it can indicate the date is related to some calendar (Japanese, Gregorian, Hijri...).
    maybe we can come up with a name which can work and not conflict with VB. something like AbsoluteDate, PureDate...etc.

  8. paulirwin commented on Feb 10, 2015

    @paulirwin
    Author

    @mj1856 Thanks for the detailed comments! Regarding VB, I assume an "Option" flag a la "Option Strict" is off the table? :-) Alternatively, couldn't we leave VB's Date keyword to mean System.DateTime, but allow them to do Imports Date = System.Date as a type alias?

  9. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    Imports Date = System.Date won't work since Date is a language keyword. If you were to escape it, Imports [Date] = System.Date, you would also have to escape all usages, Dim dt as [Date] = [Date].Today

    @tarekgh How do you feel about CalendarDate if the type actually has a Calendar reference?

    using System.Globalization;
    
    public struct CalendarDate
    {
        private readonly Calendar _calendar;
    
        public CalendarDate(int year, int month, int day)
        {
            _calendar = new GregorianCalendar();
            // ...
        }
    
        public CalendarDate(int year, int month, int day, Calendar calendar)
        {
            _calendar = calendar;
            // ...
        }
    //...
    
  10. tarekgh commented on Feb 10, 2015

    @tarekgh
    Member

    @mj1856 CalendarDate will make sense if we are going to support all calendars with that type (as you have demonstrated in your code). I think this is not the intend from the original request to have a simple light weight Date type. I am seeing Date and CalendarDate can be used in different scenarios

  11. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    @michaelstaib - I don't think there's anything wrong with SubtractDays and similar methods, though they are essentially the same as AddDays(-days). Having them wouldn't hurt.

    But with TimeSpan, consider the case Paul gave at the top of this proposal:

    Date d5 = d.Subtract(TimeSpan.FromYears(2));`
    

    That just can't work, because TimeSpan has no FromYears method. It can't have FromYears or FromMonths because those are not discrete measurements. (Months can be 28,29,30, or 31 days, and Years can be either 365 or 366 days).

    Even with TimeSpan.FromDays - that assumes a standard day of 24 hours in length. That doesn't always align with calendars, as DST transition days can be 23 or 25 hours long.

  12. mattjohnsonpint commented on Feb 10, 2015

    @mattjohnsonpint
    Contributor

    @tarekgh - Ok. If the intention is to keep the type lightweight, meaning it's only field would be an integer representing the whole number of days since some epoch, then I understand why CalendarDate would be a potential confusion.

    I actually like System.Date - I'm just not sure how the VB folks would reconcile. Perhaps there are some VB devs that are fluent with idiomatics that could weigh in here?

  13. 51 remaining items

  14. paulirwin commented on Mar 10, 2015

    @paulirwin
    Author

    Awesome work @mj1856! I will help out with your repo rather than trying to create my own prototype. I like the direction here.

  15. tarekgh commented on Mar 10, 2015

    @tarekgh
    Member

    @mj1856 Thanks Matt for your effort. I took a quick look at the Date type and here is some notes and questions:

    • does Date need to implement IConvertible interface. I think it is needed
    • Date will be exactly like DateTime in term of supporting Gregorian dates only. this can be ok if this satisfy all scenarios we are introducing Date for (SQL, Xml...etc.). if there is any other scenarios need to work with other calendars we'll need to either add such support here or we'll have another type like CalendarDate or so.
    • Did you think in supporting B.C dates? just raising the thought
    • does it make it easier if you store ticks instead of daynumber? avoid converting to ticks in many places
    • ToString(string format), would be ok if some one passing format include time? not a problem but just wondering
    • In general from my experience with DateTime, Parse/TryParse is really problem and always causing problems especially when changing the culture default date/time patterns. I suggest we don't support Parse/TryParse and force only ParseExact/TryParseExact
    • renaming DateFromDateTime to FromDateTime would be better I guess
    • if we have Add/Subtract methods, then I think we need to limit the parameters to positive values. otherwise we should have Add only. I am trying to limit the confusion when using it
    • I like the implicit cast operator :-)

    Thanks again Matt

  16. mattjohnsonpint commented on Mar 10, 2015

    @mattjohnsonpint
    Contributor

    @tarekgh - I'm very glad I can do this in the open source space now. It helps to include feedback from other community members. :)

    I'll address the specific points over here. Thanks!

  17. paulirwin commented on Mar 13, 2015

    @paulirwin
    Author

    As @tarekgh mentioned on @mj1856's repo, the idea is that this issue should be closed until it is proven in the field. I did not pick up on that from earlier comments here but if that's how it should be handled then that's acceptable. Personally, I think that if there is an intention to implement this in the future, then the issue should be left open, perhaps given a future milestone or tag, because otherwise will be difficult to determine when, exactly, it is "proven" in the field. Is there a way to quantify that? Should I re-open this issue when I've deployed a single app to production successfully using @mj1856's library, or does it take X users/projects/months/stars/forks before it is proven? That's an honest question, I'm not trying to be inflammatory. I just really, sincerely care about this issue - the headaches having to shoe-horn calendar dates into DateTime has wasted numerous hours of my life - and I'd be sad if it falls by the wayside due to a "won't fix" closed status and I'd like to re-open it if it legitimately meets some criteria for being proven. If there is no objective criteria for this being proven, I'd say we should keep this issue open until it is given a definitive "fixed" or "won't fix" status.

  18. paulirwin commented on Mar 13, 2015

    @paulirwin
    Author

    Also another reason for not closing the issue - if it is closed, someone else could come along, see no open issues for this, and create a new open issue, starting this conversation all over again.

  19. tarekgh commented on Mar 13, 2015

    @tarekgh
    Member

    @paulirwin this means we cannot close any issue :-) when someone open same issue again we'll direct him/her to the old issue. this is regular process for any issue. they will not have to re-discuss it again. and even they will have the freedom to reopen the old issue

  20. paulirwin commented on Mar 13, 2015

    @paulirwin
    Author

    Fair enough, then we can close the issue if that's the consensus here. But please either follow @mj1856's library closely going forward or let me know what the rough criteria would be for the library being considered proven.

  21. tarekgh commented on Mar 13, 2015

    @tarekgh
    Member

    we should be in contact with @mj1856 moving forward anyway and we'll recommend this library for anyone run into to this issue. yes we should keep our eye on this library.
    personally, I think this library will grow in good way as we have more scenarios related to date/time which may need similar solutions.

    Thanks Paul for your thoughts and bringing such issue. and thanks of course to Matt helping with the design and implementation

  22. mattjohnsonpint commented on Mar 13, 2015

    @mattjohnsonpint
    Contributor

    Thanks @tarekgh! Yes - I'm fine with closing the issue for now.

    We'll keep iterating on mj1856/corefx-dateandtime. I'll also put together examples of corefx/coreclr changes that would be compelling use cases for should it be merged.

  23. transferred this issue fromdotnet/corefxon Jan 31, 2020
  24. added this to the 1.0.0-rtm milestone on Jan 31, 2020
  25. ghost locked as resolved and limited conversation to collaborators on Jan 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

api-needs-workAPI needs work before it is approved, it is NOT ready for implementationarea-System.DateTime

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions