Just included now: ISO 8601-2 2019 Extended Date Time Format Profile (EDTF) support.
You can use the new ExtendedDateTime
class just as you would use the .NET DateTime
class, with most of the conversions between ExtendedDateTime
, DateTime
and DateOnly
supported.
All formats specified in the standard are supported. The implementation is based on the EDTF.NET implementation which was based on the draft of the ISO standard.
Example:
var someWhenInThe60s = new ExtendedDateTime("1960S2");
var longAgo = new ExtendedDateTime("Y-3388E2S3"); // yes, thats some year between 338000 and 338999, estimated to be 338800
var fourYearsIn1670 = new ExtendedDateTime("1670..1673");
var someDayInSpring = new ExtendedDateTime("2021-21");
var aRange = new ExtendedDateTime("..1983-12-31,1984-10-10..1984-11-01,1984-11-05.."); // somewhen before 1983 and between 1984-10-10 and 1984-11-01 and after 1984-11-05
You see, there are many possibilities to specify dates and date ranges.
Documentation is lacking a bit still, but this will be remedied soon. Some minor code cleanups are to be done still too.
PS: I would love to include full ISO 8601-2 2019 support, but thats a big chunk to bite off, maybe some day. Volunteers are welcome though.
This library is built from the ground up to be a simple, easy to use, and intuitive date and time library for .NET, that simplifies common tasks and provides a consistent API for working with dates and times, throughout the DateTime, DateOnly, TimeOnly and TimeSpan .NET objects. It adds many operations that one expects to find in a date and time library, but are missing from the .NET standard library. Currently it features over 300 methods to deal with dates and times and ranges (periods) thereof.
It is however not intended to be a replacement for any part of the standard .NET library, but rather an extension to it. It is built upon the existing .NET standard library and does not replace any of the existing functionality. It is also not intended to be a replacement for the NodaTime library, but it can be used in conjunction.
Conversions between the types or operations with mixed types (use DateTime and DateOnly for example without converting one into the other manually) are possible.
For example: NextWeek()
to advance a DateTime or DateOnly to the same weekday in the next week, NextYear()
to add a year to a DateTime or DateOlnly object (yes, of course you can use the existing .AddYears(1)
method, but it does not look as clear), NextWorkday()
to advance the DateTime or DateOnly object to the next working day on the given Calendar
.
Or things like IsWeekend()
which of course you can also do with myDate.DayOfWeek == DayOfWeek.Saturday || myDate.DayOfWeek == DayOfWeek.Sunday
, but it just aint as nice to read. Then we also have IsWorkday()
which is the opposite of IsWeekend()
and also IsHoliday()
which checks if the given date is a holiday on the given calendar.
Not to mention the IsBetween()
method which is a very useful method to check if a date is between two other dates. It also supports the DateOnly
and TimeOnly
objects.
For more elaborate operations we have the Enumerations, like EnumerateDaysUntil
, EnumerateMonthsUntil
, EnumerateYearsUntil
, EnumerateWeeksUntil
, EnumerateWorkdaysUntil
, EnumerateWeekendsUntil
, EnumerateHolidaysUntil
.
Finally you can add minutes to a DateOnly
object (given its more than a day) -> myDate.AddMinutes(525600); // thats a year in minutes
or even hours or seconds if you wish so.
Want to know the FirstMondayOfTheMonth? -> myDate.FirstMondayOfTheMonth()
or the LastFridayOfTheMonth? -> myDate.LastFridayOfTheMonth()
. How often did you need already to know the first or last day of the month? -> myDate.FirstDayOfTheMonth()
or myDate.LastDayOfTheMonth()
.
Need to know the number of workdays in a period? -> myDate.NumberOfDaysUntil()
or the number of holidays in a period? -> myDate.NumberOfHolidaysUntil()
.
You can also create custom enumerations with EnumerateInStepsUntil
which allows you to create enumerations from a start date or time until a end date or time in steps specified by a TimeSpan
. Like in
void ListAllDaysNotHolidays(DateOnly startDate)
{
// you can provide also a Calendar object to the EnumerateInStepsUntil method if the current Culture is not adequate
var myEnum = startDate.EnumerateInStepsUntil(startDate.AddMonths(6), TimeSpan.FromDays(1), SkipHolidays);
foreach (var item in myEnum)
{
Console.WriteLine(item);
}
bool SkipHolidays(DateOnly date) => return !date.IsHoliday();
}
Another sample, create 10 minute spans over a week, but skip midnight
void Get10MinuteSpans(DateTime startDate)
{
var myEnum = startDate.EnumerateInStepsUntil(startDate.NextWeek(), TimeSpan.FromMinutes(10), SkipMidnight);
foreach (var item in myEnum)
{
Console.WriteLine(item);
}
bool SkipMidnight(DateTime date)
{
return !date.IsMidnight();
}
}
You got your own IDateTimeProvider
through which you can inject your own date and time and supports mocking directly. Instead of DateTime.Utcnow
you can use DateTimeProvider.Current.UtcNow
and always get the date and time you expect.
Just install the NuGet package and you are ready to go! It's mostly built upon common sense when using Date and Time objects in .NET.
For Holiday calculations it uses the Nager.Date library, but you need to bring your own license key. There is also a DefaultHolidayProvider() which knows only the very few international holidays and is the default. Optionally you can use your own provider through the IHolidayProvider
interface and the DateTimeProvider.SetHolidayProvider()
method.
Documentation is mostly complete, although there may be some missing or even wrong descriptions (copy paste errors usually). If you find something missing or wrong, please let me know.
Unit tests cover ~98%, a few edge cases are not covered yet. So there is a high confidence that the code is working correctly.
The NuGet package is available via NuGet
PM> install-package MoreDateTime