diff --git a/readme.md b/readme.md
index a944800f9..79ab0e674 100644
--- a/readme.md
+++ b/readme.md
@@ -44,6 +44,7 @@ Humanizer meets all your .NET needs for manipulating and displaying strings, enu
- [ByteSize](#bytesize)
- [Heading to words](#heading-to-words)
- [Tupleize](#tupleize)
+ - [Time unit to symbol](#timeunit-to-symbol)
- [Mix this into your framework to simplify your life](#mix-this-into-your-framework-to-simplify-your-life) -
- [How to contribute?](#how-to-contribute)
- [Continuous Integration from AppVeyor](#continuous-integration)
@@ -1109,6 +1110,18 @@ Humanizer can change whole numbers into their 'tuple' using `Tupleize`. For exa
The numbers 1-10, 100 and 1000 will be converted into a 'named' tuple (i.e. "single", "double" etc.). Any other number "n" will be converted to "n-tuple".
+### Time unit to symbol
+Humanizer can translate time units to their symbols:
+
+```C#
+TimeUnit.Day.ToSymbol();
+// d
+TimeUnit.Week.ToSymbol();
+// week
+TimeUnit.Year.ToSymbol();
+// y
+```
+
## Mix this into your framework to simplify your life
This is just a baseline and you can use this to simplify your day to day job. For example, in Asp.Net MVC we keep chucking `Display` attribute on ViewModel properties so `HtmlHelper` can generate correct labels for us; but, just like enums, in vast majority of cases we just need a space between the words in property name - so why not use `"string".Humanize` for that?!
diff --git a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
index 17c44126e..590113f49 100644
--- a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
+++ b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
@@ -71,6 +71,7 @@
+
@@ -203,6 +204,7 @@
+
diff --git a/src/Humanizer.Tests.Shared/Localisation/de/TimeUnitToSymbolTests.cs b/src/Humanizer.Tests.Shared/Localisation/de/TimeUnitToSymbolTests.cs
new file mode 100644
index 000000000..2b334ba26
--- /dev/null
+++ b/src/Humanizer.Tests.Shared/Localisation/de/TimeUnitToSymbolTests.cs
@@ -0,0 +1,27 @@
+using System;
+
+using Humanizer.Localisation;
+
+using Xunit;
+
+namespace Humanizer.Tests.Localisation.de
+{
+ [UseCulture("de-DE")]
+ public class TimeUnitToSymbolTests
+ {
+ [Theory]
+ [Trait("Translation", "Native speaker")]
+ [InlineData(TimeUnit.Millisecond, "ms")]
+ [InlineData(TimeUnit.Second, "s")]
+ [InlineData(TimeUnit.Minute, "min")]
+ [InlineData(TimeUnit.Hour, "h")]
+ [InlineData(TimeUnit.Day, "d")]
+ [InlineData(TimeUnit.Week, "Woche")]
+ [InlineData(TimeUnit.Month, "M")]
+ [InlineData(TimeUnit.Year, "a")]
+ public void ToSymbol(TimeUnit unit, string expected)
+ {
+ Assert.Equal(expected, unit.ToSymbol());
+ }
+ }
+}
diff --git a/src/Humanizer.Tests.Shared/TimeUnitToSymbolTests.cs b/src/Humanizer.Tests.Shared/TimeUnitToSymbolTests.cs
new file mode 100644
index 000000000..759b17e1e
--- /dev/null
+++ b/src/Humanizer.Tests.Shared/TimeUnitToSymbolTests.cs
@@ -0,0 +1,24 @@
+using Humanizer.Localisation;
+
+using Xunit;
+
+namespace Humanizer.Tests
+{
+ [UseCulture("en-US")]
+ public class TimeUnitToSymbolTests
+ {
+ [Theory]
+ [InlineData(TimeUnit.Millisecond, "ms")]
+ [InlineData(TimeUnit.Second, "s")]
+ [InlineData(TimeUnit.Minute, "min")]
+ [InlineData(TimeUnit.Hour, "h")]
+ [InlineData(TimeUnit.Day, "d")]
+ [InlineData(TimeUnit.Week, "week")]
+ [InlineData(TimeUnit.Month, "mo")]
+ [InlineData(TimeUnit.Year, "y")]
+ public void ToSymbol(TimeUnit unit, string expected)
+ {
+ Assert.Equal(expected, unit.ToSymbol());
+ }
+ }
+}
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 53cfd1a1c..f41cef7d1 100644
--- a/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt
+++ b/src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt
@@ -1583,6 +1583,10 @@ namespace Humanizer
public static string Humanize(this System.TimeSpan timeSpan, int precision = 1, System.Globalization.CultureInfo culture = null, Humanizer.Localisation.TimeUnit maxUnit = 5, Humanizer.Localisation.TimeUnit minUnit = 0, string collectionSeparator = ", ", bool toWords = False) { }
public static string Humanize(this System.TimeSpan timeSpan, int precision, bool countEmptyUnits, System.Globalization.CultureInfo culture = null, Humanizer.Localisation.TimeUnit maxUnit = 5, Humanizer.Localisation.TimeUnit minUnit = 0, string collectionSeparator = ", ", bool toWords = False) { }
}
+ public class static TimeUnitToSymbolExtensions
+ {
+ public static string ToSymbol(this Humanizer.Localisation.TimeUnit unit, System.Globalization.CultureInfo culture = null) { }
+ }
public class static To
{
public static Humanizer.ICulturedStringTransformer LowerCase { get; }
@@ -1852,6 +1856,10 @@ namespace Humanizer.Localisation
{
public static string GetResourceKey(Humanizer.Localisation.TimeUnit unit, int count = 1, bool toWords = False) { }
}
+ public class static TimeUnitSymbol
+ {
+ public static string GetResourceKey(Humanizer.Localisation.TimeUnit unit) { }
+ }
}
public class static Resources
{
@@ -1902,6 +1910,7 @@ namespace Humanizer.Localisation.Formatters
protected virtual string GetResourceKey(string resourceKey) { }
public virtual string TimeSpanHumanize(Humanizer.Localisation.TimeUnit timeUnit, int unit, bool toWords = False) { }
public virtual string TimeSpanHumanize_Zero() { }
+ public virtual string TimeUnitHumanize(Humanizer.Localisation.TimeUnit timeUnit) { }
}
public interface IFormatter
{
@@ -1911,6 +1920,7 @@ namespace Humanizer.Localisation.Formatters
string DateHumanize_Now();
string TimeSpanHumanize(Humanizer.Localisation.TimeUnit timeUnit, int unit, bool toWords = False);
string TimeSpanHumanize_Zero();
+ string TimeUnitHumanize(Humanizer.Localisation.TimeUnit timeUnit);
}
}
namespace Humanizer.Localisation.NumberToWords
diff --git a/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
index d3b410990..baa74d7e6 100644
--- a/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
+++ b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
@@ -83,6 +83,13 @@ public virtual string DataUnitHumanize(DataUnit dataUnit, double count, bool toS
return resourceValue;
}
+ ///
+ public virtual string TimeUnitHumanize(TimeUnit timeUnit)
+ {
+ var resourceKey = ResourceKeys.TimeUnitSymbol.GetResourceKey(timeUnit);
+ return Format(resourceKey);
+ }
+
private string GetResourceForDate(TimeUnit unit, Tense timeUnitTense, int count)
{
var resourceKey = ResourceKeys.DateHumanize.GetResourceKey(unit, timeUnitTense: timeUnitTense, count: count);
diff --git a/src/Humanizer/Localisation/Formatters/IFormatter.cs b/src/Humanizer/Localisation/Formatters/IFormatter.cs
index 64e06c3dd..772d66c24 100644
--- a/src/Humanizer/Localisation/Formatters/IFormatter.cs
+++ b/src/Humanizer/Localisation/Formatters/IFormatter.cs
@@ -51,5 +51,12 @@ public interface IFormatter
/// Indicates whether the data unit should be expressed as symbol or full word
/// String representation of the provided DataUnit
string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol = true);
+
+ ///
+ /// Returns the symbol for the given TimeUnit
+ ///
+ /// Time unit
+ /// String representation of the provided TimeUnit
+ string TimeUnitHumanize(TimeUnit timeUnit);
}
}
diff --git a/src/Humanizer/Localisation/ResourceKeys.TimeUnitSymbol.cs b/src/Humanizer/Localisation/ResourceKeys.TimeUnitSymbol.cs
new file mode 100644
index 000000000..c008fdb47
--- /dev/null
+++ b/src/Humanizer/Localisation/ResourceKeys.TimeUnitSymbol.cs
@@ -0,0 +1,28 @@
+namespace Humanizer.Localisation
+{
+ public partial class ResourceKeys
+ {
+ ///
+ /// Encapsulates the logic required to get the resource keys for TimeUnit.ToSymbol
+ ///
+ public static class TimeUnitSymbol
+ {
+ ///
+ /// Examples: TimeUnit_Minute, TimeUnit_Hour.
+ ///
+ private const string TimeUnitFormat = "TimeUnit_{0}";
+
+ ///
+ /// Generates Resource Keys according to convention.
+ ///
+ /// Time unit, .
+ /// Number of units, default is One.
+ /// Result to words, default is false.
+ /// Resource key, like TimeSpanHumanize_SingleMinute
+ public static string GetResourceKey(TimeUnit unit)
+ {
+ return TimeUnitFormat.FormatWith(unit);
+ }
+ }
+ }
+}
diff --git a/src/Humanizer/Properties/Resources.de.resx b/src/Humanizer/Properties/Resources.de.resx
index 37f688366..b127c0b49 100644
--- a/src/Humanizer/Properties/Resources.de.resx
+++ b/src/Humanizer/Properties/Resources.de.resx
@@ -402,4 +402,28 @@
TB
+
+ ms
+
+
+ s
+
+
+ min
+
+
+ h
+
+
+ d
+
+
+ Woche
+
+
+ M
+
+
+ a
+
\ No newline at end of file
diff --git a/src/Humanizer/Properties/Resources.resx b/src/Humanizer/Properties/Resources.resx
index 8683674b6..d1c7050c4 100644
--- a/src/Humanizer/Properties/Resources.resx
+++ b/src/Humanizer/Properties/Resources.resx
@@ -711,4 +711,28 @@
TB
+
+ ms
+
+
+ s
+
+
+ min
+
+
+ h
+
+
+ d
+
+
+ week
+
+
+ mo
+
+
+ y
+
\ No newline at end of file
diff --git a/src/Humanizer/TimeUnitToSymbolExtensions.cs b/src/Humanizer/TimeUnitToSymbolExtensions.cs
new file mode 100644
index 000000000..86a3b6bd6
--- /dev/null
+++ b/src/Humanizer/TimeUnitToSymbolExtensions.cs
@@ -0,0 +1,24 @@
+using System.Globalization;
+
+using Humanizer.Localisation;
+using Humanizer.Configuration;
+
+namespace Humanizer
+{
+ ///
+ /// Transform a time unit into a symbol; e.g. => "a"
+ ///
+ public static class TimeUnitToSymbolExtensions
+ {
+ ///
+ /// TimeUnit.Day.ToSymbol() -> "d"
+ ///
+ /// Unit of time to be turned to a symbol
+ /// Culture to use. If null, current thread's UI culture is used.
+ ///
+ public static string ToSymbol(this TimeUnit unit, CultureInfo culture = null)
+ {
+ return Configurator.GetFormatter(culture).TimeUnitHumanize(unit);
+ }
+ }
+}