Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert TimeUnit to symbols #1106

Merged
merged 4 commits into from Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions readme.md
Expand Up @@ -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)
Expand Down Expand Up @@ -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".

### <a id="timeunit-to-symbol">Time unit to symbol</a>
Humanizer can translate time units to their symbols:

```C#
TimeUnit.Day.ToSymbol();
// d
TimeUnit.Week.ToSymbol();
// week
TimeUnit.Year.ToSymbol();
// a
```

## <a id="mix-this-into-your-framework-to-simplify-your-life">Mix this into your framework to simplify your life</a>
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?!

Expand Down
2 changes: 2 additions & 0 deletions src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
Expand Up @@ -71,6 +71,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Localisation\de\HeadingTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\de\OrdinalizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\de\TimeSpanHumanizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\de\TimeUnitToSymbolTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\el\DateHumanizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\el\TimeSpanHumanizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Localisation\en\DateToOrdinalWordsTests.cs" />
Expand Down Expand Up @@ -203,6 +204,7 @@
<Compile Include="$(MSBuildThisFileDirectory)StringExtensionsTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StringHumanizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TimeSpanHumanizeTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TimeUnitToSymbolTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ToQuantityTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TransformersTests.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TruncatorTests.cs" />
Expand Down
@@ -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());
}
}
}
24 changes: 24 additions & 0 deletions 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, "a")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the a mean here? Not sure I've seen this before, is there an example you can point to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took it from Wikipedia, which listed both "a" (per annum?) and "y" (per year) as possible versions in English. Will fix as discussed. 👍🏻

public void ToSymbol(TimeUnit unit, string expected)
{
Assert.Equal(expected, unit.ToSymbol());
}
}
}
Expand Up @@ -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; }
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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
{
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
Expand Up @@ -83,6 +83,13 @@ public virtual string DataUnitHumanize(DataUnit dataUnit, double count, bool toS
return resourceValue;
}

/// <inheritdoc />
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);
Expand Down
7 changes: 7 additions & 0 deletions src/Humanizer/Localisation/Formatters/IFormatter.cs
Expand Up @@ -51,5 +51,12 @@ public interface IFormatter
/// <param name="toSymbol">Indicates whether the data unit should be expressed as symbol or full word</param>
/// <returns>String representation of the provided DataUnit</returns>
string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol = true);

/// <summary>
/// Returns the symbol for the given TimeUnit
/// </summary>
/// <param name="timeUnit">Time unit</param>
/// <returns>String representation of the provided TimeUnit</returns>
string TimeUnitHumanize(TimeUnit timeUnit);
}
}
28 changes: 28 additions & 0 deletions src/Humanizer/Localisation/ResourceKeys.TimeUnitSymbol.cs
@@ -0,0 +1,28 @@
namespace Humanizer.Localisation
{
public partial class ResourceKeys
{
/// <summary>
/// Encapsulates the logic required to get the resource keys for TimeUnit.ToSymbol
/// </summary>
public static class TimeUnitSymbol
{
/// <summary>
/// Examples: TimeUnit_Minute, TimeUnit_Hour.
/// </summary>
private const string TimeUnitFormat = "TimeUnit_{0}";

/// <summary>
/// Generates Resource Keys according to convention.
/// </summary>
/// <param name="unit">Time unit, <see cref="TimeUnit"/>.</param>
/// <param name="count">Number of units, default is One.</param>
/// <param name="toWords">Result to words, default is false.</param>
/// <returns>Resource key, like TimeSpanHumanize_SingleMinute</returns>
public static string GetResourceKey(TimeUnit unit)
{
return TimeUnitFormat.FormatWith(unit);
}
}
}
}
24 changes: 24 additions & 0 deletions src/Humanizer/Properties/Resources.de.resx
Expand Up @@ -402,4 +402,28 @@
<data name="DataUnit_TerabyteSymbol" xml:space="preserve">
<value>TB</value>
</data>
<data name="TimeUnit_Millisecond" xml:space="preserve">
<value>ms</value>
</data>
<data name="TimeUnit_Second" xml:space="preserve">
<value>s</value>
</data>
<data name="TimeUnit_Minute" xml:space="preserve">
<value>min</value>
</data>
<data name="TimeUnit_Hour" xml:space="preserve">
<value>h</value>
</data>
<data name="TimeUnit_Day" xml:space="preserve">
<value>d</value>
</data>
<data name="TimeUnit_Week" xml:space="preserve">
<value>Woche</value>
</data>
<data name="TimeUnit_Month" xml:space="preserve">
<value>M</value>
</data>
<data name="TimeUnit_Year" xml:space="preserve">
<value>a</value>
</data>
</root>
24 changes: 24 additions & 0 deletions src/Humanizer/Properties/Resources.resx
Expand Up @@ -711,4 +711,28 @@
<data name="DataUnit_TerabyteSymbol" xml:space="preserve">
<value>TB</value>
</data>
<data name="TimeUnit_Millisecond" xml:space="preserve">
<value>ms</value>
</data>
<data name="TimeUnit_Second" xml:space="preserve">
<value>s</value>
</data>
<data name="TimeUnit_Minute" xml:space="preserve">
<value>min</value>
</data>
<data name="TimeUnit_Hour" xml:space="preserve">
<value>h</value>
</data>
<data name="TimeUnit_Day" xml:space="preserve">
<value>d</value>
</data>
<data name="TimeUnit_Week" xml:space="preserve">
<value>week</value>
</data>
<data name="TimeUnit_Month" xml:space="preserve">
<value>mo</value>
</data>
<data name="TimeUnit_Year" xml:space="preserve">
<value>a</value>
hangy marked this conversation as resolved.
Show resolved Hide resolved
</data>
</root>
24 changes: 24 additions & 0 deletions src/Humanizer/TimeUnitToSymbolExtensions.cs
@@ -0,0 +1,24 @@
using System.Globalization;

using Humanizer.Localisation;
using Humanizer.Configuration;

namespace Humanizer
{
/// <summary>
/// Transform a time unit into a symbol; e.g. <see cref="TimeUnit.Year"/> => "a"
/// </summary>
public static class TimeUnitToSymbolExtensions
{
/// <summary>
/// TimeUnit.Day.ToSymbol() -> "d"
/// </summary>
/// <param name="unit">Unit of time to be turned to a symbol</param>
/// <param name="culture">Culture to use. If null, current thread's UI culture is used.</param>
/// <returns></returns>
public static string ToSymbol(this TimeUnit unit, CultureInfo culture = null)
{
return Configurator.GetFormatter(culture).TimeUnitHumanize(unit);
}
}
}