Skip to content

Commit

Permalink
Add DateToWords Feature
Browse files Browse the repository at this point in the history
Add date to words converter feature.
Support for en, en-US and es language.
  • Loading branch information
CiscoAstrum committed Jun 6, 2022
1 parent 606e958 commit 7fd79ad
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/Humanizer.Tests.Shared/Localisation/en/DateToWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using Xunit;

namespace Humanizer.Tests.Localisation.en
{
public class DateToWordsTests
{
[UseCulture("en-GB")]
[Fact]
public void ConvertDateToWordsGbString()
{
Assert.Equal("the first of January two thousand and twenty-two", new DateTime(2022, 1, 1).ToWords());
}

[UseCulture("en-US")]
[Fact]
public void ConvertDateToWordsUsString()
{
Assert.Equal("January first, two thousand and twenty-two", new DateTime(2022, 1, 1).ToWords());
}

#if NET6_0_OR_GREATER
[UseCulture("en-GB")]
[Fact]
public void ConvertDateOnlyToWordsGbString()
{
Assert.Equal("the first of January two thousand and twenty-two", new DateOnly(2022, 1, 1).ToWords());
}

[UseCulture("en-US")]
[Fact]
public void ConvertDateOnlyToWordsUsString()
{
Assert.Equal("January first, two thousand and twenty-two", new DateOnly(2022, 1, 1).ToWords());
}
#endif
}
}
29 changes: 29 additions & 0 deletions src/Humanizer.Tests.Shared/Localisation/es/DateToWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using Xunit;

namespace Humanizer.Tests.Localisation.es
{
[UseCulture("es-419")]
public class DateToWordsTests
{
[Fact]
public void ConvertDateToWordsString()
{
Assert.Equal("dos de enero de dos mil veintidós", new DateTime(2022, 1, 2).ToWords());
Assert.Equal("diez de junio de dos mil veinte", new DateTime(2020, 6, 10).ToWords());
Assert.Equal("veinticinco de septiembre de dos mil diecisiete", new DateTime(2017, 9, 25).ToWords());
Assert.Equal("treinta y uno de diciembre de mil novecientos noventa y nueve", new DateTime(1999, 12, 31).ToWords());
}

#if NET6_0_OR_GREATER
[Fact]
public void ConvertDateOnlyToWordsString()
{
Assert.Equal("dos de enero de dos mil veintidós", new DateOnly(2022, 1, 2).ToWords());
Assert.Equal("diez de junio de dos mil veinte", new DateOnly(2020, 6, 10).ToWords());
Assert.Equal("veinticinco de septiembre de dos mil diecisiete", new DateOnly(2017, 9, 25).ToWords());
Assert.Equal("treinta y uno de diciembre de mil novecientos noventa y nueve", new DateOnly(1999, 12, 31).ToWords());
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ namespace Humanizer
public static string ToOrdinalWords(this System.DateOnly input) { }
public static string ToOrdinalWords(this System.DateOnly input, Humanizer.GrammaticalCase grammaticalCase) { }
}
public class static DateToWordsExtensions
{
public static string ToWords(this System.DateTime input) { }
public static string ToWords(this System.DateTime input, Humanizer.GrammaticalCase grammaticalCase) { }
public static string ToWords(this System.DateOnly input) { }
public static string ToWords(this System.DateOnly input, Humanizer.GrammaticalCase grammaticalCase) { }
}
public class static EnglishArticle
{
public static string[] AppendArticlePrefix(string[] items) { }
Expand Down Expand Up @@ -1757,9 +1764,11 @@ namespace Humanizer.Configuration
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.CollectionFormatters.ICollectionFormatter> CollectionFormatters { get; }
public static Humanizer.DateTimeHumanizeStrategy.IDateOnlyHumanizeStrategy DateOnlyHumanizeStrategy { get; set; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.DateToOrdinalWords.IDateOnlyToOrdinalWordConverter> DateOnlyToOrdinalWordsConverters { get; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.DateToWords.IDateOnlyToWordConverter> DateOnlyToWordsConverters { get; }
public static Humanizer.DateTimeHumanizeStrategy.IDateTimeHumanizeStrategy DateTimeHumanizeStrategy { get; set; }
public static Humanizer.DateTimeHumanizeStrategy.IDateTimeOffsetHumanizeStrategy DateTimeOffsetHumanizeStrategy { get; set; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.DateToOrdinalWords.IDateToOrdinalWordConverter> DateToOrdinalWordsConverters { get; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.DateToWords.IDateToWordConverter> DateToWordsConverters { get; }
public static System.Func<System.Reflection.PropertyInfo, bool> EnumDescriptionPropertyLocator { get; set; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.Formatters.IFormatter> Formatters { get; }
public static Humanizer.Configuration.LocaliserRegistry<Humanizer.Localisation.NumberToWords.INumberToWordsConverter> NumberToWordsConverters { get; }
Expand Down Expand Up @@ -1928,6 +1937,19 @@ namespace Humanizer.Localisation.DateToOrdinalWords
string Convert(System.DateTime date, Humanizer.GrammaticalCase grammaticalCase);
}
}
namespace Humanizer.Localisation.DateToWords
{
public interface IDateOnlyToWordConverter
{
string Convert(System.DateOnly date);
string Convert(System.DateOnly date, Humanizer.GrammaticalCase grammaticalCase);
}
public interface IDateToWordConverter
{
string Convert(System.DateTime date);
string Convert(System.DateTime date, Humanizer.GrammaticalCase grammaticalCase);
}
}
namespace Humanizer.Localisation.Formatters
{
public class DefaultFormatter : Humanizer.Localisation.Formatters.IFormatter
Expand Down
49 changes: 49 additions & 0 deletions src/Humanizer/Configuration/Configurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Humanizer.DateTimeHumanizeStrategy;
using Humanizer.Localisation.CollectionFormatters;
using Humanizer.Localisation.DateToOrdinalWords;
using Humanizer.Localisation.DateToWords;
using Humanizer.Localisation.Formatters;
using Humanizer.Localisation.NumberToWords;
using Humanizer.Localisation.Ordinalizers;
Expand Down Expand Up @@ -64,6 +65,15 @@ public static LocaliserRegistry<IDateToOrdinalWordConverter> DateToOrdinalWordsC
get { return _dateToOrdinalWordConverters; }
}

private static readonly LocaliserRegistry<IDateToWordConverter> _dateToWordConverters = new DateToWordsConverterRegistry();
/// <summary>
/// A registry of date to words converters used to localise ToWords method
/// </summary>
public static LocaliserRegistry<IDateToWordConverter> DateToWordsConverters
{
get { return _dateToWordConverters; }
}

#if NET6_0_OR_GREATER
private static readonly LocaliserRegistry<IDateOnlyToOrdinalWordConverter> _dateOnlyToOrdinalWordConverters = new DateOnlyToOrdinalWordsConverterRegistry();
/// <summary>
Expand All @@ -74,6 +84,15 @@ public static LocaliserRegistry<IDateOnlyToOrdinalWordConverter> DateOnlyToOrdin
get { return _dateOnlyToOrdinalWordConverters; }
}

private static readonly LocaliserRegistry<IDateOnlyToWordConverter> _dateOnlyToWordConverters = new DateOnlyToWordsConverterRegistry();
/// <summary>
/// A registry of date to words converters used to localise ToWords method
/// </summary>
public static LocaliserRegistry<IDateOnlyToWordConverter> DateOnlyToWordsConverters
{
get { return _dateOnlyToWordConverters; }
}

private static readonly LocaliserRegistry<ITimeOnlyToClockNotationConverter> _timeOnlyToClockNotationConverters = new TimeOnlyToClockNotationConvertersRegistry();
/// <summary>
/// A registry of time to clock notation converters used to localise ToClockNotation methods
Expand Down Expand Up @@ -132,6 +151,17 @@ internal static IDateToOrdinalWordConverter DateToOrdinalWordsConverter
}
}

/// <summary>
/// The converter of date to Words to be used
/// </summary>
internal static IDateToWordConverter DateToWordsConverter
{
get
{
return DateToWordsConverters.ResolveForUiCulture();
}
}

#if NET6_0_OR_GREATER
/// <summary>
/// The ordinalizer to be used
Expand All @@ -151,6 +181,25 @@ internal static ITimeOnlyToClockNotationConverter TimeOnlyToClockNotationConvert
return TimeOnlyToClockNotationConverters.ResolveForUiCulture();
}
}

/// <summary>
/// The converter of date to Words to be used
/// </summary>
internal static IDateOnlyToWordConverter DateOnlyToWordsConverter
{
get
{
return DateOnlyToWordsConverters.ResolveForUiCulture();
}
}

//internal static ITimeOnlyToClockNotationConverter TimeOnlyToClockNotationConverter
//{
// get
// {
// return TimeOnlyToClockNotationConverters.ResolveForUiCulture();
// }
//}
#endif

private static IDateTimeHumanizeStrategy _dateTimeHumanizeStrategy = new DefaultDateTimeHumanizeStrategy();
Expand Down
15 changes: 15 additions & 0 deletions src/Humanizer/Configuration/DateOnlyToWordsConverterRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#if NET6_0_OR_GREATER
using Humanizer.Localisation.DateToWords;

namespace Humanizer.Configuration
{
internal class DateOnlyToWordsConverterRegistry : LocaliserRegistry<IDateOnlyToWordConverter>
{
public DateOnlyToWordsConverterRegistry() : base(new DefaultDateOnlyToWordConverter())
{
Register("en-US", new UsDateOnlyToWordsConverter());
Register("es", new EsDateOnlyToWordsConverter());
}
}
}
#endif
13 changes: 13 additions & 0 deletions src/Humanizer/Configuration/DateToWordsConverterRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Humanizer.Localisation.DateToWords;

namespace Humanizer.Configuration
{
internal class DateToWordsConverterRegistry : LocaliserRegistry<IDateToWordConverter>
{
public DateToWordsConverterRegistry() : base(new DefaultDateToWordConverter())
{
Register("en-US", new UsDateToWordsConverter());
Register("es", new EsDateToWordsConverter());
}
}
}
53 changes: 53 additions & 0 deletions src/Humanizer/DateToWordsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using Humanizer.Configuration;

namespace Humanizer
{
/// <summary>
/// Humanizes DateTime into human readable sentence
/// </summary>
public static class DateToWordsExtensions
{
/// <summary>
/// Turns the provided date into words
/// </summary>
/// <param name="input">The date to be made into words</param>
/// <returns>The date in words</returns>
public static string ToWords(this DateTime input)
{
return Configurator.DateToWordsConverter.Convert(input);
}
/// <summary>
/// Turns the provided date into words
/// </summary>
/// <param name="input">The date to be made into words</param>
/// <param name="grammaticalCase">The grammatical case to use for output words</param>
/// <returns>The date in words</returns>
public static string ToWords(this DateTime input, GrammaticalCase grammaticalCase)
{
return Configurator.DateToWordsConverter.Convert(input, grammaticalCase);
}

#if NET6_0_OR_GREATER
/// <summary>
/// Turns the provided date into words
/// </summary>
/// <param name="input">The date to be made into words</param>
/// <returns>The date in words</returns>
public static string ToWords(this DateOnly input)
{
return Configurator.DateOnlyToWordsConverter.Convert(input);
}
/// <summary>
/// Turns the provided date into words
/// </summary>
/// <param name="input">The date to be made into words</param>
/// <param name="grammaticalCase">The grammatical case to use for output words</param>
/// <returns>The date in words</returns>
public static string ToWords(this DateOnly input, GrammaticalCase grammaticalCase)
{
return Configurator.DateOnlyToWordsConverter.Convert(input, grammaticalCase);
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#if NET6_0_OR_GREATER

using System;

namespace Humanizer.Localisation.DateToWords
{
internal class DefaultDateOnlyToWordConverter : IDateOnlyToWordConverter
{

public virtual string Convert(DateOnly date)
{
return "the " + date.Day.ToOrdinalWords() + date.ToString(" 'of' MMMM ") + date.Year.ToWords();
}

public virtual string Convert(DateOnly date, GrammaticalCase grammaticalCase)
{
return Convert(date);
}

}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Humanizer.Localisation.DateToWords
{
internal class DefaultDateToWordConverter : IDateToWordConverter
{

public virtual string Convert(DateTime date)
{
return "the " + date.Day.ToOrdinalWords() + date.ToString(" 'of' MMMM ") + date.Year.ToWords();
}

public virtual string Convert(DateTime date, GrammaticalCase grammaticalCase)
{
return Convert(date);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#if NET6_0_OR_GREATER

using System;
using Humanizer.Configuration;

namespace Humanizer.Localisation.DateToWords
{
internal class EsDateOnlyToWordsConverter : DefaultDateOnlyToWordConverter
{
public override string Convert(DateOnly date)
{
var equivalentDateTime = date.ToDateTime(TimeOnly.MinValue);
return Configurator.DateToWordsConverter.Convert(equivalentDateTime);
}
}
}

#endif
12 changes: 12 additions & 0 deletions src/Humanizer/Localisation/DateToWords/EsDateToWordsConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Humanizer.Localisation.DateToWords
{
internal class EsDateToWordsConverter : DefaultDateToWordConverter
{
public override string Convert(DateTime date)
{
return date.Day.ToWords() + date.ToString(" 'de' MMMM 'de' ") + date.Year.ToWords();
}
}
}
28 changes: 28 additions & 0 deletions src/Humanizer/Localisation/DateToWords/IDateOnlyToWordConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#if NET6_0_OR_GREATER

using System;

namespace Humanizer.Localisation.DateToWords
{
/// <summary>
/// The interface used to localise the ToWords method.
/// </summary>
public interface IDateOnlyToWordConverter
{
/// <summary>
/// Converts the date to Words
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
string Convert(DateOnly date);

/// <summary>
/// Converts the date to Words using the provided grammatical case
/// </summary>
/// <param name="date"></param>
/// <param name="grammaticalCase"></param>
/// <returns></returns>
string Convert(DateOnly date, GrammaticalCase grammaticalCase);
}
}
#endif
Loading

0 comments on commit 7fd79ad

Please sign in to comment.