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

time span format verbosity #1183

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
16 changes: 12 additions & 4 deletions readme.md
Expand Up @@ -436,10 +436,10 @@ When there are multiple time units, they are combined using the `", "` string:
TimeSpan.FromMilliseconds(1299630020).Humanize(3) => "2 weeks, 1 day, 1 hour"
```

When `TimeSpan` is zero, the default behavior will return "0" plus whatever the minimum time unit is. However, if you assign `true` to `toWords` when calling `Humanize`, then the method returns "no time". For example:
When `TimeSpan` is zero, the default behavior will return "0" plus whatever the minimum time unit is. However, if you assign `TimeSpanStyle.Words` to `timeSpanStyle` when calling `Humanize`, then the method returns "no time". For example:
```C#
TimeSpan.Zero.Humanize(1) => "0 milliseconds"
TimeSpan.Zero.Humanize(1, toWords: true) => "no time"
TimeSpan.Zero.Humanize(1, timeSpanStyle: TimeSpanStyle.Words) => "no time"
TimeSpan.Zero.Humanize(1, minUnit: Humanizer.Localisation.TimeUnit.Second) => "0 seconds"
```

Expand All @@ -459,9 +459,17 @@ TimeSpan.FromMilliseconds(1299630020).Humanize(3, collectionSeparator: null) =>
TimeSpan.FromMilliseconds(1299630020).Humanize(3, collectionSeparator: null) => "2 Wochen, Ein Tag und Eine Stunde"
```

If words are preferred to numbers, a `toWords: true` parameter can be set to convert the numbers in a humanized TimeSpan to words:
If words are preferred to numbers, a `timeSpanStyle: TimeSpanStyle.Words` parameter can be set to convert the numbers in a humanized TimeSpan to words:
```C#
TimeSpan.FromMilliseconds(1299630020).Humanize(3, toWords: true) => "two weeks, one day, one hour"
TimeSpan.FromMilliseconds(1299630020).Humanize(3, timeSpanStyle: TimeSpanStyle.Words) => "two weeks, one day, one hour"
````

It is also possible to choose to return an abbreviated or short representation of the time span
(English only).
This is done by specifying `timeSpanStyle: TimeSpanStyle.Abbreviated` or `timeSpanStyle: TimeSpanStyle.Short` as a parameter:
```C#
TimeSpan.FromWeeks(1).Humanize(timeSpanStyle: TimeSpanStyle.Abbreviated) => "1 wk"
TimeSpan.FromWeeks(1).Humanize(timeSpanStyle: TimeSpanStyle.Short) => "1w"
````

### <a id="humanize-collections">Humanize Collections</a>
Expand Down
2 changes: 0 additions & 2 deletions src/Humanizer.Tests.Shared/InflectorTests.cs
Expand Up @@ -30,8 +30,6 @@ namespace Humanizer.Tests
{
public class InflectorTests
{
public readonly IList<object[]> PluralTestData = new List<object[]>();

[Theory]
[ClassData(typeof(PluralTestSource))]
public void Pluralize(string singular, string plural)
Expand Down
Expand Up @@ -116,7 +116,7 @@ public void NoTime()
[Fact]
public void NoTimeToWords()
{
Assert.Equal("geen tyd", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("geen tyd", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -98,7 +98,7 @@ public void NoTime()
[Fact]
public void NoTimeToWords()
{
Assert.Equal("حالاً", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("حالاً", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -95,7 +95,7 @@ public void NoTime()
public void NoTimeToWords()
{
var noTime = TimeSpan.Zero;
var actual = noTime.Humanize(toWords: true);
var actual = noTime.Humanize(timeSpanStyle: TimeSpanStyle.Words);
Assert.Equal("zaman fərqi yoxdur", actual);
}
}
Expand Down
Expand Up @@ -86,7 +86,7 @@ public void NoTime()
[Fact]
public void NoTimeToWords()
{
Assert.Equal("няма време", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("няма време", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -87,7 +87,7 @@ public void NoTime()
public void NoTimeToWords()
{
// This one really doesn't make a lot of sense but again... w/e
Assert.Equal("শূন্য সময়", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("শূন্য সময়", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -86,7 +86,7 @@ public void NoTime()
[Fact]
public void NoTimeToWords()
{
Assert.Equal("ingen tid", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("ingen tid", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -25,7 +25,7 @@ public void Years(int days, string expected)
[InlineData(4018, "elf Jahre")]
public void YearsToWords(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year,toWords:true));
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year, timeSpanStyle: TimeSpanStyle.Words));
}

[Theory]
Expand All @@ -47,7 +47,7 @@ public void Months(int days, string expected)
[InlineData(335, "elf Monate")]
public void MonthsToWords(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year,toWords:true));
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year, timeSpanStyle: TimeSpanStyle.Words));
}

[Theory]
Expand All @@ -67,7 +67,7 @@ public void Weeks(int days, string expected)
[InlineData(77, "elf Wochen")]
public void WeeksToWords(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}


Expand All @@ -84,7 +84,7 @@ public void Days(int days, string expected)
[InlineData(2, "zwei Tage")]
public void DaysToWords(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}

[Theory]
Expand All @@ -100,7 +100,7 @@ public void Hours(int hours, string expected)
[InlineData(2, "zwei Stunden")]
public void HoursToWords(int hours, string expected)
{
Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}

[Theory]
Expand All @@ -116,7 +116,7 @@ public void Minutes(int minutes, string expected)
[InlineData(2, "zwei Minuten")]
public void MinutesToWords(int minutes, string expected)
{
Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}


Expand All @@ -133,7 +133,7 @@ public void Seconds(int seconds, string expected)
[InlineData(2, "zwei Sekunden")]
public void SecondsToWords(int seconds, string expected)
{
Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}

[Theory]
Expand All @@ -149,7 +149,7 @@ public void Milliseconds(int milliseconds, string expected)
[InlineData(2, "zwei Millisekunden")]
public void MillisecondsToWords(int milliseconds, string expected)
{
Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize(toWords: true));
Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize(timeSpanStyle: TimeSpanStyle.Words));
}

[Fact]
Expand All @@ -162,7 +162,7 @@ public void NoTime()
public void NoTimeToWords()
{
// This one doesn't make a lot of sense but ... w/e
Assert.Equal("Keine Zeit", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("Keine Zeit", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
Expand Up @@ -89,7 +89,7 @@ public void NoTime()
[Fact]
public void NoTimeToWords()
{
Assert.Equal("μηδέν χρόνος", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("μηδέν χρόνος", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}
}
}
68 changes: 34 additions & 34 deletions src/Humanizer.Tests.Shared/Localisation/es/TimeSpanHumanizeTests.cs
Expand Up @@ -118,7 +118,7 @@ public void OneMillisecond()
public void ComplexTimeSpan(int days, int hours, int minutes, int seconds, int precision, string expected)
{
var timeSpan = new TimeSpan(days, hours, minutes, seconds);
Assert.Equal(expected, timeSpan.Humanize(precision, toWords: true));
Assert.Equal(expected, timeSpan.Humanize(precision, timeSpanStyle: TimeSpanStyle.Words));
}

[Fact]
Expand All @@ -132,7 +132,7 @@ public void NoTime()
public void NoTimeToWords()
{
// This one doesn't make a lot of sense but ... w/e
Assert.Equal("nada", TimeSpan.Zero.Humanize(toWords: true));
Assert.Equal("nada", TimeSpan.Zero.Humanize(timeSpanStyle: TimeSpanStyle.Words));
}

[Fact]
Expand Down Expand Up @@ -280,49 +280,49 @@ public void TimeSpanWithMaxTimeUnit(long ms, string expected, TimeUnit maxUnit)

[Theory]
[InlineData(10, "10 milisegundos", TimeUnit.Millisecond)]
[InlineData(10, "nada", TimeUnit.Second, true)]
[InlineData(10, "nada", TimeUnit.Minute, true)]
[InlineData(10, "nada", TimeUnit.Hour, true)]
[InlineData(10, "nada", TimeUnit.Day, true)]
[InlineData(10, "nada", TimeUnit.Week, true)]
[InlineData(10, "nada", TimeUnit.Second, TimeSpanStyle.Words)]
[InlineData(10, "nada", TimeUnit.Minute, TimeSpanStyle.Words)]
[InlineData(10, "nada", TimeUnit.Hour, TimeSpanStyle.Words)]
[InlineData(10, "nada", TimeUnit.Day, TimeSpanStyle.Words)]
[InlineData(10, "nada", TimeUnit.Week, TimeSpanStyle.Words)]
[InlineData(10, "0 segundos", TimeUnit.Second)]
[InlineData(10, "0 minutos", TimeUnit.Minute)]
[InlineData(10, "0 horas", TimeUnit.Hour)]
[InlineData(10, "0 días", TimeUnit.Day)]
[InlineData(10, "0 semanas", TimeUnit.Week)]
[InlineData(2500, "2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(2500, "2 segundos", TimeUnit.Second)]
[InlineData(2500, "nada", TimeUnit.Minute, true)]
[InlineData(2500, "nada", TimeUnit.Hour, true)]
[InlineData(2500, "nada", TimeUnit.Day, true)]
[InlineData(2500, "nada", TimeUnit.Week, true)]
[InlineData(2500, "nada", TimeUnit.Minute, TimeSpanStyle.Words)]
[InlineData(2500, "nada", TimeUnit.Hour, TimeSpanStyle.Words)]
[InlineData(2500, "nada", TimeUnit.Day, TimeSpanStyle.Words)]
[InlineData(2500, "nada", TimeUnit.Week, TimeSpanStyle.Words)]
[InlineData(2500, "0 minutos", TimeUnit.Minute)]
[InlineData(2500, "0 horas", TimeUnit.Hour)]
[InlineData(2500, "0 días", TimeUnit.Day)]
[InlineData(2500, "0 semanas", TimeUnit.Week)]
[InlineData(122500, "2 minutos, 2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(122500, "2 minutos, 2 segundos", TimeUnit.Second)]
[InlineData(122500, "2 minutos", TimeUnit.Minute)]
[InlineData(122500, "nada", TimeUnit.Hour, true)]
[InlineData(122500, "nada", TimeUnit.Day, true)]
[InlineData(122500, "nada", TimeUnit.Week, true)]
[InlineData(122500, "nada", TimeUnit.Hour, TimeSpanStyle.Words)]
[InlineData(122500, "nada", TimeUnit.Day, TimeSpanStyle.Words)]
[InlineData(122500, "nada", TimeUnit.Week, TimeSpanStyle.Words)]
[InlineData(122500, "0 horas", TimeUnit.Hour)]
[InlineData(122500, "0 días", TimeUnit.Day)]
[InlineData(122500, "0 semanas", TimeUnit.Week)]
[InlineData(3722500, "1 hora, 2 minutos, 2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(3722500, "1 hora, 2 minutos, 2 segundos", TimeUnit.Second)]
[InlineData(3722500, "1 hora, 2 minutos", TimeUnit.Minute)]
[InlineData(3722500, "1 hora", TimeUnit.Hour)]
[InlineData(3722500, "nada", TimeUnit.Day, true)]
[InlineData(3722500, "nada", TimeUnit.Week, true)]
[InlineData(3722500, "nada", TimeUnit.Day, TimeSpanStyle.Words)]
[InlineData(3722500, "nada", TimeUnit.Week, TimeSpanStyle.Words)]
[InlineData(3722500, "0 días", TimeUnit.Day)]
[InlineData(3722500, "0 semanas", TimeUnit.Week)]
[InlineData(90122500, "1 día, 1 hora, 2 minutos, 2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(90122500, "1 día, 1 hora, 2 minutos, 2 segundos", TimeUnit.Second)]
[InlineData(90122500, "1 día, 1 hora, 2 minutos", TimeUnit.Minute)]
[InlineData(90122500, "1 día, 1 hora", TimeUnit.Hour)]
[InlineData(90122500, "1 día", TimeUnit.Day)]
[InlineData(90122500, "nada", TimeUnit.Week, true)]
[InlineData(90122500, "nada", TimeUnit.Week, TimeSpanStyle.Words)]
[InlineData(90122500, "0 semanas", TimeUnit.Week)]
[InlineData(694922500, "1 semana, 1 día, 1 hora, 2 minutos, 2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(694922500, "1 semana, 1 día, 1 hora, 2 minutos, 2 segundos", TimeUnit.Second)]
Expand All @@ -337,7 +337,7 @@ public void TimeSpanWithMaxTimeUnit(long ms, string expected, TimeUnit maxUnit)
[InlineData(2768462500, "1 mes, 1 día", TimeUnit.Day)]
[InlineData(2768462500, "1 mes", TimeUnit.Week)]
[InlineData(2768462500, "1 mes", TimeUnit.Month)]
[InlineData(2768462500, "nada", TimeUnit.Year, true)]
[InlineData(2768462500, "nada", TimeUnit.Year, TimeSpanStyle.Words)]
[InlineData(2768462500, "0 años", TimeUnit.Year)]
[InlineData(34390862500, "1 año, 1 mes, 2 días, 1 hora, 1 minuto, 2 segundos, 500 milisegundos", TimeUnit.Millisecond)]
[InlineData(34390862500, "1 año, 1 mes, 2 días, 1 hora, 1 minuto, 2 segundos", TimeUnit.Second)]
Expand All @@ -347,15 +347,15 @@ public void TimeSpanWithMaxTimeUnit(long ms, string expected, TimeUnit maxUnit)
[InlineData(34390862500, "1 año, 1 mes", TimeUnit.Week)]
[InlineData(34390862500, "1 año, 1 mes", TimeUnit.Month)]
[InlineData(34390862500, "1 año", TimeUnit.Year)]
public void TimeSpanWithMinTimeUnit(long ms, string expected, TimeUnit minUnit, bool toWords = false)
public void TimeSpanWithMinTimeUnit(long ms, string expected, TimeUnit minUnit, TimeSpanStyle timeSpanStyle = TimeSpanStyle.Full)
{
var actual = TimeSpan.FromMilliseconds(ms).Humanize(minUnit: minUnit, precision: 7, maxUnit: TimeUnit.Year, toWords: toWords);
var actual = TimeSpan.FromMilliseconds(ms).Humanize(minUnit: minUnit, precision: 7, maxUnit: TimeUnit.Year, timeSpanStyle: timeSpanStyle);
Assert.Equal(expected, actual);
}

[Theory]
[InlineData(0, 3, "nada", true)]
[InlineData(0, 2, "nada", true)]
[InlineData(0, 3, "nada", TimeSpanStyle.Words)]
[InlineData(0, 2, "nada", TimeSpanStyle.Words)]
[InlineData(0, 3, "0 milisegundos")]
[InlineData(0, 2, "0 milisegundos")]
[InlineData(10, 2, "10 milisegundos")]
Expand Down Expand Up @@ -398,9 +398,9 @@ public void TimeSpanWithMinTimeUnit(long ms, string expected, TimeUnit minUnit,
[InlineData(34390862500, 3, "1 año, 1 mes, 2 días")]
[InlineData(34390862500, 2, "1 año, 1 mes")]
[InlineData(34390862500, 1, "1 año")]
public void TimeSpanWithPrecision(long milliseconds, int precision, string expected, bool toWords = false)
public void TimeSpanWithPrecision(long milliseconds, int precision, string expected, TimeSpanStyle timeSpanStyle = TimeSpanStyle.Full)
{
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, maxUnit: TimeUnit.Year, toWords: toWords);
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, maxUnit: TimeUnit.Year, timeSpanStyle: timeSpanStyle);
Assert.Equal(expected, actual);
}

Expand All @@ -419,14 +419,14 @@ public void DaysWithPrecision(int days, int precision, string expected)
[InlineData(52)]
public void TimeSpanWithMinAndMaxUnits_DoesNotReportExcessiveTime(int minutes)
{
var actual = TimeSpan.FromMinutes(minutes).Humanize(2, null, TimeUnit.Hour, TimeUnit.Minute);
var actual = TimeSpan.FromMinutes(minutes).Humanize(2, maxUnit: TimeUnit.Hour, minUnit: TimeUnit.Minute);
var expected = TimeSpan.FromMinutes(minutes).Humanize(2);
Assert.Equal(expected, actual);
}

[Theory]
[InlineData(0, 3, "nada", true)]
[InlineData(0, 2, "nada", true)]
[InlineData(0, 3, "nada", TimeSpanStyle.Words)]
[InlineData(0, 2, "nada", TimeSpanStyle.Words)]
[InlineData(0, 3, "0 milisegundos")]
[InlineData(0, 2, "0 milisegundos")]
[InlineData(10, 2, "10 milisegundos")]
Expand Down Expand Up @@ -462,15 +462,15 @@ public void TimeSpanWithMinAndMaxUnits_DoesNotReportExcessiveTime(int minutes)
[InlineData(1299630020, 4, "2 semanas, 1 día, 1 hora")]
[InlineData(1299630020, 5, "2 semanas, 1 día, 1 hora, 30 segundos")]
[InlineData(1299630020, 6, "2 semanas, 1 día, 1 hora, 30 segundos, 20 milisegundos")]
public void TimeSpanWithPrecisionAndCountingEmptyUnits(int milliseconds, int precision, string expected, bool toWords = false)
public void TimeSpanWithPrecisionAndCountingEmptyUnits(int milliseconds, int precision, string expected, TimeSpanStyle timeSpanStyle = TimeSpanStyle.Full)
{
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision: precision, countEmptyUnits: true, toWords: toWords);
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision: precision, countEmptyUnits: true, timeSpanStyle: timeSpanStyle);
Assert.Equal(expected, actual);
}

[Theory]
[InlineData(0, 3, "nada", true)]
[InlineData(0, 2, "nada", true)]
[InlineData(0, 3, "nada", TimeSpanStyle.Words)]
[InlineData(0, 2, "nada", TimeSpanStyle.Words)]
[InlineData(0, 3, "0 milisegundos")]
[InlineData(0, 2, "0 milisegundos")]
[InlineData(10, 2, "10 milisegundos")]
Expand Down Expand Up @@ -501,9 +501,9 @@ public void TimeSpanWithPrecisionAndCountingEmptyUnits(int milliseconds, int pre
[InlineData(1299630020, 4, "2 semanas, 1 día, 1 hora y 30 segundos")]
[InlineData(1299630020, 5, "2 semanas, 1 día, 1 hora, 30 segundos y 20 milisegundos")]
public void TimeSpanWithPrecisionAndAlternativeCollectionFormatter(int milliseconds, int precision,
string expected, bool toWords = false)
string expected, TimeSpanStyle timeSpanStyle = TimeSpanStyle.Full)
{
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, collectionSeparator: null, toWords: toWords);
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, collectionSeparator: null, timeSpanStyle: timeSpanStyle);
Assert.Equal(expected, actual);
}

Expand Down Expand Up @@ -539,7 +539,7 @@ public void TimeSpanWithPrecisionAndCountingEmptyUnits(int milliseconds, int pre
[InlineData(1299630020, 5, "dos semanas, un día, una hora, treinta segundos, veinte milisegundos")]
public void TimeSpanWithNumbersConvertedToWords(int milliseconds, int precision, string expected)
{
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, toWords: true);
var actual = TimeSpan.FromMilliseconds(milliseconds).Humanize(precision, timeSpanStyle: TimeSpanStyle.Words);
Assert.Equal(expected, actual);
}
}
Expand Down