Expand API surface for DateTime, DateTimeOffset, DateOnly, TimeOnly, and TimeSpan

Open
#113,033 22 comments 16 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
csharp

Research direction

The issue names no source files, entry points, or tests and proposes a broad API expansion across five date and time types. Start by reviewing the existing APIs against the numbered proposals, then narrow the scope to a specific, accepted change. Done requires a decided API proposal before implementation can begin.

Written by the indexing model from the issue text.

Description

api-suggestion area-System.DateTime

Background and Motivation

Almost every project I've worked on, from small personal projects to large enterprise ones, ends up with various extension methods designed to make date and time manipulation more concise and less repetitive. Many of these are born out of inconsistencies and/or shortcomings of the current API surface on the five core date and time types: DateTime, DateTimeOffset, DateOnly, TimeOnly, and TimeSpan. Specifically, DateOnly and TimeOnly do not feel like first class citizens next to DateTime and DateTimeOffset.

In an ecosystem where version after version, compiler and syntax changes have been consitently made to reduce the amount of syntax needed to create types (ie: collection expressions), I feel like these core system types have not been given the same amount of attention. Yet date and time manipulation is probably one of the most common operations and omni present in almost every single project a .NET developer will be involved in.

Proposed API

To avoid creating a large amount of issues that are all centered around the same background and motivation, I opted instead on creating a list of proposed APIs with additional notes where appropriate. I have tried to group them as best as I can.

Missing APIs for consistency
1) DateTimeOffset.FromDateTime(DateTime dateTime) static method
  • DateOnly and TimeOnly both already expose FromDateTime().
  • A DateTime can already be cast into a DateTimeOffset.
2) DateTime.FromDateTimeOffset() static method
  • There is already a constructor overload on DateTimeOffset which supports a DateTime.
  • With proposal 1, DateTimeOffset would also expose the similar FromDateTime().
3) dateTime.ToDateTimeOffset(TimeSpan offset) instance method
  • There is already a constructor overload on DateTimeOffset which supports a DateTime and TimeSpan.
  • DateOnly instances already expose the similar ToDateTime.
4) DateTimeOffset.Today and DateOnly.Today property
  • DateTimeOffset already exposes Now and UtcNow like DateTime.
  • DateTime already exposes Today.
5) TimeOnly.Now and TimeOnly.UtcNow property
  • DateTime and DateTimeOffset already expose Now and UtcNow.
6) timeOnly.AddSeconds(double value), timeOnly.AddMilliseconds(double value), timeOnly.AddMicroseconds(double value), and timeOnly.AddTicks(long value) instance method
  • DateTime and DateTimeOffset instances both already expose AddSeconds(), AddMilliseconds(), AddMicroseconds(), and AddTicks().
7) DateOnly.FromDateTimeOffset(DateTimeOffset dateTimeOffset) and TimeOnly.FromDateTimeOffset(DateTimeOffset dateTimeOffset) static methods
  • DateOnly and TimeOnly both already expose FromDateTime().
8) DateTime.FromDateOnly(DateOnly dateOnly) and DateTimeOffset.FromDateOnly(DateOnly dateOnly) static methods
  • DateOnly and TimeOnly both already expose FromDateTime().
9) dateTime.ToDateOnly() instance method
  • DateOnly instances already expose ToDateTime().
10) dateTimeOffset.ToDateOnly() instance method
  • DateOnly instances already expose ToDateTime().
  • With proposal 9, DateTime instances would also expose ToDateOnly().
11) dateOnly.ToDateTimeOffset() and dateOnly.ToDateTimeOffset(TimeSpan offset) instance methods
  • DateOnly instances already expose ToDateTime().
  • With proposal 9 and 10, DateTime instances would also expose ToDateOnly() and DateTimeOffset instances would also expose .ToDateOnly().
12) dateTime.ToTimeOnly() and dateTimeOffset.ToTimeOnly() instance methods
  • DateOnly instances already expose ToDateTime().
  • With proposal 9, 10, and 11, DateTime instances would also expose ToDateOnly(), DateTimeOffset instances would also expose .ToDateOnly(), and DateOnly instances would also expose .ToDateTimeOffset().
13) Implicit cast from DateOnly instances to DateTimeOffset instances
  • DateTime instances already implicitly cast to DateTimeOffset.
Expanding Today API
14) DateTime.UtcToday, DateTimeOffset.UtcToday, DateOnly.UtcToday
  • DateTime and DateTimeOffset already expose the properties Now and UtcNow, this would be natural pairing to the already exposed Today property.
  • With proposal 4, both DateTimeOffset and DateOnly would also expose Today.
New Substract APIs
15) Substract instance method variants of Add to DateTime, DateTimeOffset, DateOnly, and TimeOnly
  • Add the SubstractYears(int value) instance method to DateTime, DateTimeOffset, and DateOnly.
  • Add the SubstractMonths(int value) instance method to DateTime, DateTimeOffset, and DateOnly.
  • Add the SubstractDays(double value) instance method to DateTime, DateTimeOffset, and SubstractDays(int value) instance method DateOnly.
  • Add the SubstractHours(double value) instance method to DateTime, DateTimeOffset, and TimeOnly.
  • Add the SubstractMinutes(double value) instance method to DateTime, DateTimeOffset, and TimeOnly.
  • Add the SubstractSeconds(double value) instance method to DateTime, DateTimeOffset, and TimeOnly.
  • Add the SubstractMilliseconds(double value) instance method to DateTime, DateTimeOffset, and TimeOnly.
  • Add the SubstractMicroseconds(double value) instance method to DateTime, DateTimeOffset, and TimeOnly.
  • Add the SubstractTicks(long value) instance method to DateTime, DateTimeOffset, and TimeOnly.
Expand TimeSpan API

16) TimeSpan.FromYears(int value) and TimeSpan.FromMonths(int value) static methods

  • TimeSpan already exposes all other From methods.
17) TimeSpan.Add variants and TimeSpan.Substract variants
  • Adding the AddYears(), AddMonths(), AddDays(), AddHours(), AddMinutes(), AddSeconds(), AddMilliseconds(), AddMicroseconds(), AddTicks() instance methods would avoid needing to create an intermediate TimeSpan to manipulate an existing TimeSpan.
  • Also in the same vein, adding the instance methods from proposal 15.
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/runtime

All issues in dotnet/runtime

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.