Skip to content

DateOnly should have a matching Span type #54400

@DrkWzrd

Description

@DrkWzrd

Background and Motivation

I apologize in advance for my English.

TimeSpan is fine, but managing big time spans (years, months) with it (or, in the worst case, with DateTime struct) is so frustrating (and in DateTime case, incoherent). In real world there are so many scenarios where we use larger time spans than just a few days.

Therefore, I think DateOnly introduction should be accompanied with a DateSpan type (because I understand adding APIs like Months, or Years to TimeSpan should not be right). making computations with DateOnly easier, and more clear and straightforward when we are developing.

And DateOnly has this APIs, but separated in every field (days, months and years), and are backed by DateTime internally, but I think we need a structure to represent that, a DateSpan. a Date"Period" (something like TimeSpan, but with bigger concepts like weeks, months and years; like NodaTime Period).

E.g.: if i talk with someone about an appointment in "3 months" or "2 weeks", or "4 years" this numbers are so big to manage it in days values with TimeSpan. In addition, if we are working with DateOnly types, it doesn't make sense to use an XXXXSpan struct which accepts values smaller than days.

With this struct should be able to operate with DateOnly types (e.g.: operators like +, -, etc are not included right now).

Proposed API

    namespace System
    {
        public readonly struct DateSpan : IEquatable<DateSpan>, IFormattable, IComparable, IComparable<DateSpan>
        {

            public static DateSpan MinValue { get { throw null; } }
            public static DateSpan MaxValue { get { throw null; } }

            public int Days { get { throw null; } }
            public int Months { get { throw null; } }
            public int Years { get { throw null; } }

            public int TotalDays { get { throw null; } } //the lesser unit allowed should be days, then total days can be an integer
            public double TotalMonths { get { throw null; } }
            public double TotalYears { get { throw null; } }

            public int CompareTo(DateSpan other) { throw new NotImplementedException(); }
            public int CompareTo(object obj) { throw new NotImplementedException(); }
            public bool Equals(DateSpan other) { throw new NotImplementedException(); }
            public string ToString(string format, IFormatProvider formatProvider) { throw new NotImplementedException(); }

            public static DateSpan operator +(DateSpan ds1, DateSpan ds2) { throw null; }
            public static DateSpan operator -(DateSpan ds1, DateSpan ds2) { throw null; }

            public static implicit operator TimeSpan(DateSpan ds1) { throw null; } //something like this:  return new TimeSpan(ds1.TotalDays, 0, 0, 0, 0);
            public static implicit operator DateSpan(TimeSpan ts1) { throw null; }
        }

    }

Usage Examples

This API should allow this new operators

    public struct DateOnly
    {
        public static DateSpan operator -(DateOnly do1, DateOnly do2) { throw null; }

        public static DateOnly operator +(DateOnly do1, DateSpan ds1) { throw null; }
    }

    public struct DateTime
    {
        public static DateSpan operator -(DateTime dt1, DateTime dt2) { throw null; }
        public static DateTime operator +(DateTime dt1, DateSpan ds1) { throw null; }
    }

Risks

The one main risk I can see is the confusion of usage between TimeSpan and DateSpan. But I'm sure there are a lot I haven't thought.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions