From b2491d8f699189776a91450afc4e2b2d5c082d97 Mon Sep 17 00:00:00 2001 From: Claire Novotny Date: Mon, 7 Jun 2021 13:28:16 -0400 Subject: [PATCH] Add support for DateOnly to ordinal words --- .../de/DateToOrdinalWordsTests.cs | 8 ++++++ .../en/DateToOrdinalWordsTests.cs | 16 +++++++++++ ...provalTest.approve_public_api.approved.txt | 8 ++++++ src/Humanizer/Configuration/Configurator.cs | 24 ++++++++++++++++ ...DateOnlyToOrdinalWordsConverterRegistry.cs | 16 +++++++++++ src/Humanizer/DateHumanizeExtensions.cs | 4 +-- src/Humanizer/DateToOrdinalWordsExtensions.cs | 24 +++++++++++++++- .../DefaultDateOnlyToOrdinalWordConverter.cs | 23 +++++++++++++++ .../IDateOnlyToOrdinalWordConverter.cs | 28 +++++++++++++++++++ .../UsDateOnlyToOrdinalWordsConverter.cs | 14 ++++++++++ 10 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 src/Humanizer/Configuration/DateOnlyToOrdinalWordsConverterRegistry.cs create mode 100644 src/Humanizer/Localisation/DateToOrdinalWords/DefaultDateOnlyToOrdinalWordConverter.cs create mode 100644 src/Humanizer/Localisation/DateToOrdinalWords/IDateOnlyToOrdinalWordConverter.cs create mode 100644 src/Humanizer/Localisation/DateToOrdinalWords/UsDateOnlyToOrdinalWordsConverter.cs diff --git a/src/Humanizer.Tests.Shared/Localisation/de/DateToOrdinalWordsTests.cs b/src/Humanizer.Tests.Shared/Localisation/de/DateToOrdinalWordsTests.cs index 48ed80e1c..2e2ce5370 100644 --- a/src/Humanizer.Tests.Shared/Localisation/de/DateToOrdinalWordsTests.cs +++ b/src/Humanizer.Tests.Shared/Localisation/de/DateToOrdinalWordsTests.cs @@ -11,5 +11,13 @@ public void OrdinalizeString() { Assert.Equal("1. Januar 2015", new DateTime(2015, 1, 1).ToOrdinalWords()); } + +#if NET6_0_OR_GREATER + [Fact] + public void OrdinalizeDateOnlyString() + { + Assert.Equal("1. Januar 2015", new DateOnly(2015, 1, 1).ToOrdinalWords()); + } +#endif } } diff --git a/src/Humanizer.Tests.Shared/Localisation/en/DateToOrdinalWordsTests.cs b/src/Humanizer.Tests.Shared/Localisation/en/DateToOrdinalWordsTests.cs index e1f8eb92a..0ed0b4b99 100644 --- a/src/Humanizer.Tests.Shared/Localisation/en/DateToOrdinalWordsTests.cs +++ b/src/Humanizer.Tests.Shared/Localisation/en/DateToOrdinalWordsTests.cs @@ -18,5 +18,21 @@ public void OrdinalizeStringUs() { Assert.Equal("January 1st, 2015", new DateTime(2015, 1, 1).ToOrdinalWords()); } + +#if NET6_0_OR_GREATER + [UseCulture("en-GB")] + [Fact] + public void OrdinalizeDateOnlyStringGb() + { + Assert.Equal("1st January 2015", new DateOnly(2015, 1, 1).ToOrdinalWords()); + } + + [UseCulture("en-US")] + [Fact] + public void OrdinalizeDateOnlyStringUs() + { + Assert.Equal("January 1st, 2015", new DateOnly(2015, 1, 1).ToOrdinalWords()); + } +#endif } } diff --git a/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt b/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt index 354294c69..2a2dc31ec 100644 --- a/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt +++ b/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt @@ -84,6 +84,8 @@ namespace Humanizer { public static string ToOrdinalWords(this System.DateTime input) { } public static string ToOrdinalWords(this System.DateTime input, Humanizer.GrammaticalCase grammaticalCase) { } + public static string ToOrdinalWords(this System.DateOnly input) { } + public static string ToOrdinalWords(this System.DateOnly input, Humanizer.GrammaticalCase grammaticalCase) { } } public class static EnglishArticle { @@ -1717,6 +1719,7 @@ namespace Humanizer.Configuration { public static Humanizer.Configuration.LocaliserRegistry CollectionFormatters { get; } public static Humanizer.DateTimeHumanizeStrategy.IDateOnlyHumanizeStrategy DateOnlyHumanizeStrategy { get; set; } + public static Humanizer.Configuration.LocaliserRegistry DateOnlyToOrdinalWordsConverters { get; } public static Humanizer.DateTimeHumanizeStrategy.IDateTimeHumanizeStrategy DateTimeHumanizeStrategy { get; set; } public static Humanizer.DateTimeHumanizeStrategy.IDateTimeOffsetHumanizeStrategy DateTimeOffsetHumanizeStrategy { get; set; } public static Humanizer.Configuration.LocaliserRegistry DateToOrdinalWordsConverters { get; } @@ -1872,6 +1875,11 @@ namespace Humanizer.Localisation } namespace Humanizer.Localisation.DateToOrdinalWords { + public interface IDateOnlyToOrdinalWordConverter + { + string Convert(System.DateOnly date); + string Convert(System.DateOnly date, Humanizer.GrammaticalCase grammaticalCase); + } public interface IDateToOrdinalWordConverter { string Convert(System.DateTime date); diff --git a/src/Humanizer/Configuration/Configurator.cs b/src/Humanizer/Configuration/Configurator.cs index 0e52bddc6..f9e5dcbae 100644 --- a/src/Humanizer/Configuration/Configurator.cs +++ b/src/Humanizer/Configuration/Configurator.cs @@ -61,6 +61,17 @@ public static LocaliserRegistry DateToOrdinalWordsC get { return _dateToOrdinalWordConverters; } } +#if NET6_0_OR_GREATER + private static readonly LocaliserRegistry _dateOnlyToOrdinalWordConverters = new DateOnlyToOrdinalWordsConverterRegistry(); + /// + /// A registry of ordinalizers used to localise Ordinalize method + /// + public static LocaliserRegistry DateOnlyToOrdinalWordsConverters + { + get { return _dateOnlyToOrdinalWordConverters; } + } +#endif + internal static ICollectionFormatter CollectionFormatter { get @@ -109,6 +120,19 @@ internal static IDateToOrdinalWordConverter DateToOrdinalWordsConverter } } +#if NET6_0_OR_GREATER + /// + /// The ordinalizer to be used + /// + internal static IDateOnlyToOrdinalWordConverter DateOnlyToOrdinalWordsConverter + { + get + { + return DateOnlyToOrdinalWordsConverters.ResolveForUiCulture(); + } + } +#endif + private static IDateTimeHumanizeStrategy _dateTimeHumanizeStrategy = new DefaultDateTimeHumanizeStrategy(); /// /// The strategy to be used for DateTime.Humanize diff --git a/src/Humanizer/Configuration/DateOnlyToOrdinalWordsConverterRegistry.cs b/src/Humanizer/Configuration/DateOnlyToOrdinalWordsConverterRegistry.cs new file mode 100644 index 000000000..89cdbbe45 --- /dev/null +++ b/src/Humanizer/Configuration/DateOnlyToOrdinalWordsConverterRegistry.cs @@ -0,0 +1,16 @@ +#if NET6_0_OR_GREATER + +using Humanizer.Localisation.DateToOrdinalWords; +namespace Humanizer.Configuration +{ + internal class DateOnlyToOrdinalWordsConverterRegistry : LocaliserRegistry + { + public DateOnlyToOrdinalWordsConverterRegistry() : base(new DefaultDateOnlyToOrdinalWordConverter()) + { + Register("en-UK", new DefaultDateOnlyToOrdinalWordConverter()); + Register("de", new DefaultDateOnlyToOrdinalWordConverter()); + Register("en-US", new UsDateOnlyToOrdinalWordsConverter()); + } + } +} +#endif diff --git a/src/Humanizer/DateHumanizeExtensions.cs b/src/Humanizer/DateHumanizeExtensions.cs index 025dd7c88..e1d4bd5fa 100644 --- a/src/Humanizer/DateHumanizeExtensions.cs +++ b/src/Humanizer/DateHumanizeExtensions.cs @@ -117,7 +117,7 @@ public static string Humanize(this DateOnly? input, DateOnly? dateToCompareAgain /// Turns the current or provided time into a human readable sentence /// /// The date to be humanized - /// If is null, used to determine if the current time is UTC or local. Defaults to UTC. + /// If is null, used to determine if the current time is UTC or local. Defaults to UTC. /// Date to compare the input against. If null, current date is used as base /// Culture to use. If null, current thread's UI culture is used. /// distance of time in words @@ -132,7 +132,7 @@ public static string Humanize(this TimeOnly input, TimeOnly? timeToCompareAgains /// Turns the current or provided time into a human readable sentence, overload for the nullable TimeOnly, returning 'never' in case null /// /// The date to be humanized - /// If is null, used to determine if the current time is UTC or local. Defaults to UTC. + /// If is null, used to determine if the current time is UTC or local. Defaults to UTC. /// Time to compare the input against. If null, current date is used as base /// Culture to use. If null, current thread's UI culture is used. /// distance of time in words diff --git a/src/Humanizer/DateToOrdinalWordsExtensions.cs b/src/Humanizer/DateToOrdinalWordsExtensions.cs index afb297389..9d6b1ba5c 100644 --- a/src/Humanizer/DateToOrdinalWordsExtensions.cs +++ b/src/Humanizer/DateToOrdinalWordsExtensions.cs @@ -27,5 +27,27 @@ public static string ToOrdinalWords(this DateTime input, GrammaticalCase grammat { return Configurator.DateToOrdinalWordsConverter.Convert(input, grammaticalCase); } + +#if NET6_0_OR_GREATER + /// + /// Turns the provided date into ordinal words + /// + /// The date to be made into ordinal words + /// The date in ordinal words + public static string ToOrdinalWords(this DateOnly input) + { + return Configurator.DateOnlyToOrdinalWordsConverter.Convert(input); + } + /// + /// Turns the provided date into ordinal words + /// + /// The date to be made into ordinal words + /// The grammatical case to use for output words + /// The date in ordinal words + public static string ToOrdinalWords(this DateOnly input, GrammaticalCase grammaticalCase) + { + return Configurator.DateOnlyToOrdinalWordsConverter.Convert(input, grammaticalCase); + } +#endif } -} \ No newline at end of file +} diff --git a/src/Humanizer/Localisation/DateToOrdinalWords/DefaultDateOnlyToOrdinalWordConverter.cs b/src/Humanizer/Localisation/DateToOrdinalWords/DefaultDateOnlyToOrdinalWordConverter.cs new file mode 100644 index 000000000..73aa05cdc --- /dev/null +++ b/src/Humanizer/Localisation/DateToOrdinalWords/DefaultDateOnlyToOrdinalWordConverter.cs @@ -0,0 +1,23 @@ +#if NET6_0_OR_GREATER + +using System; + +namespace Humanizer.Localisation.DateToOrdinalWords +{ + internal class DefaultDateOnlyToOrdinalWordConverter : IDateOnlyToOrdinalWordConverter + { + + public virtual string Convert(DateOnly date) + { + return date.Day.Ordinalize() + date.ToString(" MMMM yyyy"); + } + + public virtual string Convert(DateOnly date, GrammaticalCase grammaticalCase) + { + return Convert(date); + } + + } +} + +#endif diff --git a/src/Humanizer/Localisation/DateToOrdinalWords/IDateOnlyToOrdinalWordConverter.cs b/src/Humanizer/Localisation/DateToOrdinalWords/IDateOnlyToOrdinalWordConverter.cs new file mode 100644 index 000000000..a2b92f93a --- /dev/null +++ b/src/Humanizer/Localisation/DateToOrdinalWords/IDateOnlyToOrdinalWordConverter.cs @@ -0,0 +1,28 @@ +#if NET6_0_OR_GREATER + +using System; + +namespace Humanizer.Localisation.DateToOrdinalWords +{ + /// + /// The interface used to localise the ToOrdinalWords method. + /// + public interface IDateOnlyToOrdinalWordConverter + { + /// + /// Converts the date to Ordinal Words + /// + /// + /// + string Convert(DateOnly date); + + /// + /// Converts the date to Ordinal Words using the provided grammatical case + /// + /// + /// + /// + string Convert(DateOnly date, GrammaticalCase grammaticalCase); + } +} +#endif diff --git a/src/Humanizer/Localisation/DateToOrdinalWords/UsDateOnlyToOrdinalWordsConverter.cs b/src/Humanizer/Localisation/DateToOrdinalWords/UsDateOnlyToOrdinalWordsConverter.cs new file mode 100644 index 000000000..9afa4abd3 --- /dev/null +++ b/src/Humanizer/Localisation/DateToOrdinalWords/UsDateOnlyToOrdinalWordsConverter.cs @@ -0,0 +1,14 @@ +#if NET6_0_OR_GREATER +using System; + +namespace Humanizer.Localisation.DateToOrdinalWords +{ + internal class UsDateOnlyToOrdinalWordsConverter : DefaultDateOnlyToOrdinalWordConverter + { + public override string Convert(DateOnly date) + { + return date.ToString("MMMM ") + date.Day.Ordinalize() + date.ToString(", yyyy"); + } + } +} +#endif