diff --git a/readme.md b/readme.md
index d94b52fc6..4bf3de73e 100644
--- a/readme.md
+++ b/readme.md
@@ -462,6 +462,17 @@ If words are preferred to numbers, a `toWords: true` parameter can be set to con
TimeSpan.FromMilliseconds(1299630020).Humanize(3, toWords: true) => "two weeks, one day, one hour"
````
+If you would prefer and abbreviation to the complete Time Unit, a `abbreviate: true` parameter can be set to convert time units to the following abbreviations:
+ - Milliseconds: `ms`,
+ - Seconds: `s`,
+ - Minutes: `m`,
+ - Hours: `h`,
+ - Days: `d`,
+ - Weeks: `W`,
+ - Months: `M`,
+ - Years: `Y`,
+
+ Note that anything bigger then 'Days' will be capitalized.
### Humanize Collections
You can call `Humanize` on any `IEnumerable` to get a nicely formatted string representing the objects in the collection. By default `ToString()` will be called on each item to get its representation but a formatting function may be passed to `Humanize` instead. Additionally, a default separator is provided ("and" in English), but a different separator may be passed into `Humanize`.
diff --git a/src/Humanizer.Tests.Shared/TimeSpanHumanizeTests.cs b/src/Humanizer.Tests.Shared/TimeSpanHumanizeTests.cs
index 0ac198cb5..e66b56359 100644
--- a/src/Humanizer.Tests.Shared/TimeSpanHumanizeTests.cs
+++ b/src/Humanizer.Tests.Shared/TimeSpanHumanizeTests.cs
@@ -227,6 +227,15 @@ public void TimeSpanWithMinTimeUnit(long ms, string expected, TimeUnit minUnit,
Assert.Equal(expected, actual);
}
+ [Theory]
+ [InlineData(34390862500, "1 Y, 1 M, 2 d, 1 h, 1 m, 2 s, 500 ms", TimeUnit.Millisecond)]
+ [InlineData(604800000, "1 W", TimeUnit.Millisecond)]
+ public void TimeSpanWithAllUnitsAbb(long ms, string expected, TimeUnit minUnit)
+ {
+ var actual = TimeSpan.FromMilliseconds(ms).Humanize(7, maxUnit: TimeUnit.Year,toWords: false, abbreviated: true);
+ Assert.Equal(expected, actual);
+ }
+
[Theory]
[InlineData(0, 3, "no time", true)]
[InlineData(0, 2, "no time", true)]
diff --git a/src/Humanizer.Tests/Humanizer.Tests.csproj b/src/Humanizer.Tests/Humanizer.Tests.csproj
index bdfd5f692..cfcad6d43 100644
--- a/src/Humanizer.Tests/Humanizer.Tests.csproj
+++ b/src/Humanizer.Tests/Humanizer.Tests.csproj
@@ -9,6 +9,7 @@
+
diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj
index 85ff1673c..f17302c4b 100644
--- a/src/Humanizer/Humanizer.csproj
+++ b/src/Humanizer/Humanizer.csproj
@@ -12,5 +12,8 @@
true
Humanizer.snk
embedded
-
+
+
+
+
\ No newline at end of file
diff --git a/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
index 2efe8d73b..721786e61 100644
--- a/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
+++ b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs
@@ -66,9 +66,9 @@ public virtual string TimeSpanHumanize_Zero()
///
///
/// Is thrown when timeUnit is larger than TimeUnit.Week
- public virtual string TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords = false)
+ public virtual string TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords = false, bool abbreviated = false)
{
- return GetResourceForTimeSpan(timeUnit, unit, toWords);
+ return GetResourceForTimeSpan(timeUnit, unit, toWords, abbreviated);
}
private string GetResourceForDate(TimeUnit unit, Tense timeUnitTense, int count)
@@ -77,10 +77,10 @@ private string GetResourceForDate(TimeUnit unit, Tense timeUnitTense, int count)
return count == 1 ? Format(resourceKey) : Format(resourceKey, count);
}
- private string GetResourceForTimeSpan(TimeUnit unit, int count, bool toWords = false)
+ private string GetResourceForTimeSpan(TimeUnit unit, int count, bool toWords = false, bool abbreviated = false)
{
- var resourceKey = ResourceKeys.TimeSpanHumanize.GetResourceKey(unit, count, toWords);
- return count == 1 ? Format(resourceKey + (toWords ? "_Words" : "")) : Format(resourceKey, count, toWords);
+ var resourceKey = ResourceKeys.TimeSpanHumanize.GetResourceKey(unit, count, toWords, abbreviated);
+ return count == 1 && !abbreviated ? Format(resourceKey + (toWords ? "_Words" : "")) : Format(resourceKey, count, toWords);
}
///
diff --git a/src/Humanizer/Localisation/Formatters/IFormatter.cs b/src/Humanizer/Localisation/Formatters/IFormatter.cs
index 398fbd4fd..7703b36f8 100644
--- a/src/Humanizer/Localisation/Formatters/IFormatter.cs
+++ b/src/Humanizer/Localisation/Formatters/IFormatter.cs
@@ -41,6 +41,6 @@ public interface IFormatter
///
///
///
- string TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords = false);
+ string TimeSpanHumanize(TimeUnit timeUnit, int unit, bool toWords = false, bool abbreviate = false);
}
}
diff --git a/src/Humanizer/Localisation/NumberToWords/PolishNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/PolishNumberToWordsConverter.cs
index 8cf64dc9d..bd78aba19 100644
--- a/src/Humanizer/Localisation/NumberToWords/PolishNumberToWordsConverter.cs
+++ b/src/Humanizer/Localisation/NumberToWords/PolishNumberToWordsConverter.cs
@@ -43,7 +43,7 @@ public PolishNumberToWordsConverter(CultureInfo culture)
_culture = culture;
}
- public override string Convert(long input, GrammaticalGender gender)
+ public string Convert(long input, GrammaticalGender gender)
{
if (input == 0)
{
@@ -55,7 +55,12 @@ public override string Convert(long input, GrammaticalGender gender)
return string.Join(" ", parts);
}
-
+
+ public override string Convert(long number, GrammaticalGender gender, bool addAnd = true)
+ {
+ return Convert(number, gender);
+ }
+
public override string ConvertToOrdinal(int number, GrammaticalGender gender)
{
return number.ToString(_culture);
diff --git a/src/Humanizer/Localisation/ResourceKeys.Common.cs b/src/Humanizer/Localisation/ResourceKeys.Common.cs
index a8643cc06..310346136 100644
--- a/src/Humanizer/Localisation/ResourceKeys.Common.cs
+++ b/src/Humanizer/Localisation/ResourceKeys.Common.cs
@@ -9,6 +9,7 @@ public partial class ResourceKeys
{
private const string Single = "Single";
private const string Multiple = "Multiple";
+ private const string Abbreviate = "Abb";
private static void ValidateRange(int count)
{
diff --git a/src/Humanizer/Localisation/ResourceKeys.TimeSpanHumanize.cs b/src/Humanizer/Localisation/ResourceKeys.TimeSpanHumanize.cs
index a389a49bd..7b6e838c2 100644
--- a/src/Humanizer/Localisation/ResourceKeys.TimeSpanHumanize.cs
+++ b/src/Humanizer/Localisation/ResourceKeys.TimeSpanHumanize.cs
@@ -20,8 +20,9 @@ public static class TimeSpanHumanize
/// Time unit, .
/// Number of units, default is One.
/// Result to words, default is false.
+ /// Resulting units abbreviated => seconds: s. Default false
/// Resource key, like TimeSpanHumanize_SingleMinute
- public static string GetResourceKey(TimeUnit unit, int count = 1, bool toWords = false)
+ public static string GetResourceKey(TimeUnit unit, int count = 1, bool toWords = false, bool abbreviate = false)
{
ValidateRange(count);
@@ -30,6 +31,8 @@ public static string GetResourceKey(TimeUnit unit, int count = 1, bool toWords =
return Zero;
}
+ if (abbreviate) return TimeSpanFormat.FormatWith(Abbreviate, unit, "");
+
return TimeSpanFormat.FormatWith(count == 1 ? Single : Multiple, unit, count == 1 ? "" : "s");
}
}
diff --git a/src/Humanizer/Properties/Resources.fr.resx b/src/Humanizer/Properties/Resources.fr.resx
index 7cf0af1bf..aa248c097 100644
--- a/src/Humanizer/Properties/Resources.fr.resx
+++ b/src/Humanizer/Properties/Resources.fr.resx
@@ -276,4 +276,76 @@
{0} milliseconde
+
+ {0} j
+
+
+ {0} h
+
+
+ {0} ms
+
+
+ {0} m
+
+
+ {0} M
+
+
+ {0} s
+
+
+ {0} W
+
+
+ {0} Y
+
+
+ un jour
+
+
+ une heure
+
+
+ une milliseconde
+
+
+ une minute
+
+
+ un mois
+
+
+ une seconde
+
+
+ une semaine
+
+
+ un an
+
+
+ {0} semaines
+
+
+ {0} jours
+
+
+ {0} heures
+
+
+ {0} millisecondes
+
+
+ {0} minutes
+
+
+ {0} mois
+
+
+ {0} secondes
+
+
+ {0} ans
+
\ No newline at end of file
diff --git a/src/Humanizer/Properties/Resources.resx b/src/Humanizer/Properties/Resources.resx
index 678f0d5cf..805e8b048 100644
--- a/src/Humanizer/Properties/Resources.resx
+++ b/src/Humanizer/Properties/Resources.resx
@@ -675,4 +675,28 @@
NNW
+
+ {0} s
+
+
+ {0} d
+
+
+ {0} h
+
+
+ {0} ms
+
+
+ {0} m
+
+
+ {0} W
+
+
+ {0} M
+
+
+ {0} Y
+
\ No newline at end of file
diff --git a/src/Humanizer/TimeSpanHumanizeExtensions.cs b/src/Humanizer/TimeSpanHumanizeExtensions.cs
index 4fd5a0437..86390dc10 100644
--- a/src/Humanizer/TimeSpanHumanizeExtensions.cs
+++ b/src/Humanizer/TimeSpanHumanizeExtensions.cs
@@ -28,9 +28,9 @@ public static class TimeSpanHumanizeExtensions
/// The separator to use when combining humanized time parts. If null, the default collection formatter for the current culture is used.
/// Uses words instead of numbers if true. E.g. one day.
///
- public static string Humanize(this TimeSpan timeSpan, int precision = 1, CultureInfo culture = null, TimeUnit maxUnit = TimeUnit.Week, TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false)
+ public static string Humanize(this TimeSpan timeSpan, int precision = 1, CultureInfo culture = null, TimeUnit maxUnit = TimeUnit.Week, TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false, bool abbreviated = false)
{
- return Humanize(timeSpan, precision, false, culture, maxUnit, minUnit, collectionSeparator, toWords);
+ return Humanize(timeSpan, precision, false, culture, maxUnit, minUnit, collectionSeparator, toWords, abbreviated);
}
///
@@ -45,15 +45,15 @@ public static string Humanize(this TimeSpan timeSpan, int precision = 1, Culture
/// The separator to use when combining humanized time parts. If null, the default collection formatter for the current culture is used.
/// Uses words instead of numbers if true. E.g. one day.
///
- public static string Humanize(this TimeSpan timeSpan, int precision, bool countEmptyUnits, CultureInfo culture = null, TimeUnit maxUnit = TimeUnit.Week, TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false)
+ public static string Humanize(this TimeSpan timeSpan, int precision, bool countEmptyUnits, CultureInfo culture = null, TimeUnit maxUnit = TimeUnit.Week, TimeUnit minUnit = TimeUnit.Millisecond, string collectionSeparator = ", ", bool toWords = false, bool abbreviated = false)
{
- var timeParts = CreateTheTimePartsWithUpperAndLowerLimits(timeSpan, culture, maxUnit, minUnit, toWords);
+ var timeParts = CreateTheTimePartsWithUpperAndLowerLimits(timeSpan, culture, maxUnit, minUnit, toWords, abbreviated);
timeParts = SetPrecisionOfTimeSpan(timeParts, precision, countEmptyUnits);
return ConcatenateTimeSpanParts(timeParts, culture, collectionSeparator);
}
- private static IEnumerable CreateTheTimePartsWithUpperAndLowerLimits(TimeSpan timespan, CultureInfo culture, TimeUnit maxUnit, TimeUnit minUnit, bool toWords = false)
+ private static IEnumerable CreateTheTimePartsWithUpperAndLowerLimits(TimeSpan timespan, CultureInfo culture, TimeUnit maxUnit, TimeUnit minUnit, bool toWords = false, bool abbreviated = false)
{
var cultureFormatter = Configurator.GetFormatter(culture);
var firstValueFound = false;
@@ -62,7 +62,7 @@ private static IEnumerable CreateTheTimePartsWithUpperAndLowerLimits(Tim
foreach (var timeUnitType in timeUnitsEnumTypes)
{
- var timepart = GetTimeUnitPart(timeUnitType,timespan, maxUnit, minUnit, cultureFormatter, toWords);
+ var timepart = GetTimeUnitPart(timeUnitType,timespan, maxUnit, minUnit, cultureFormatter, toWords, abbreviated);
if (timepart != null || firstValueFound)
{
@@ -85,12 +85,12 @@ private static IEnumerable GetEnumTypesForTimeUnit()
return enumTypeEnumerator.Reverse();
}
- private static string GetTimeUnitPart(TimeUnit timeUnitToGet, TimeSpan timespan, TimeUnit maximumTimeUnit, TimeUnit minimumTimeUnit, IFormatter cultureFormatter, bool toWords = false)
+ private static string GetTimeUnitPart(TimeUnit timeUnitToGet, TimeSpan timespan, TimeUnit maximumTimeUnit, TimeUnit minimumTimeUnit, IFormatter cultureFormatter, bool toWords = false, bool abbreviated = false)
{
if (timeUnitToGet <= maximumTimeUnit && timeUnitToGet >= minimumTimeUnit)
{
var numberOfTimeUnits = GetTimeUnitNumericalValue(timeUnitToGet, timespan, maximumTimeUnit);
- return BuildFormatTimePart(cultureFormatter, timeUnitToGet, numberOfTimeUnits, toWords);
+ return BuildFormatTimePart(cultureFormatter, timeUnitToGet, numberOfTimeUnits, toWords, abbreviated);
}
return null;
}
@@ -179,11 +179,11 @@ private static int GetNormalCaseTimeAsInteger(int timeNumberOfUnits, double tota
return timeNumberOfUnits;
}
- private static string BuildFormatTimePart(IFormatter cultureFormatter, TimeUnit timeUnitType, int amountOfTimeUnits, bool toWords = false)
+ private static string BuildFormatTimePart(IFormatter cultureFormatter, TimeUnit timeUnitType, int amountOfTimeUnits, bool toWords = false, bool abbreviated = false)
{
// Always use positive units to account for negative timespans
return amountOfTimeUnits != 0
- ? cultureFormatter.TimeSpanHumanize(timeUnitType, Math.Abs(amountOfTimeUnits), toWords)
+ ? cultureFormatter.TimeSpanHumanize(timeUnitType, Math.Abs(amountOfTimeUnits), toWords, abbreviated)
: null;
}