Skip to content

Commit 53a1f5f

Browse files
committed
Fix ability to get months and weeks
1 parent 93b66cd commit 53a1f5f

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

src/Humanizer.Tests.Shared/TimeSpanHumanizeTests.cs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,28 @@ public void AllTimeSpansMustBeUniqueForASequenceOfDays()
1515
var culture = new CultureInfo("en-US");
1616
var qry = from i in Enumerable.Range(0, 100000)
1717
let ts = TimeSpan.FromDays(i)
18-
let text = ts.Humanize(precision: 3, culture: culture, maxUnit: TimeUnit.Year)
18+
let text = ts.Humanize(precision: 7, culture: culture, maxUnit: TimeUnit.Year)
1919
select text;
2020
var grouping = from t in qry
2121
group t by t into g
2222
select new { g.Key, Count = g.Count() };
23+
24+
var moreThanOne = grouping.Where(g => g.Count > 1).ToList();
25+
2326
var allUnique = grouping.All(g => g.Count == 1);
2427
Assert.True(allUnique);
2528
}
2629

2730
[Theory]
28-
[InlineData(365, "11 months, 30 days")]
31+
[InlineData(365, "11 months, 4 weeks, 2 days")]
2932
[InlineData(365 + 1, "1 year")]
30-
[InlineData(365 + 365, "1 year, 11 months, 29 days")]
33+
[InlineData(365 + 365, "1 year, 11 months, 4 weeks, 1 day")]
3134
[InlineData(365 + 365 + 1, "2 years")]
32-
[InlineData(365 + 365 + 365, "2 years, 11 months, 29 days")]
35+
[InlineData(365 + 365 + 365, "2 years, 11 months, 4 weeks, 1 day")]
3336
[InlineData(365 + 365 + 365 + 1, "3 years")]
34-
[InlineData(365 + 365 + 365 + 365, "3 years, 11 months, 29 days")]
37+
[InlineData(365 + 365 + 365 + 365, "3 years, 11 months, 4 weeks, 1 day")]
3538
[InlineData(365 + 365 + 365 + 365 + 1, "4 years")]
36-
[InlineData(365 + 365 + 365 + 365 + 366, "4 years, 11 months, 30 days")]
39+
[InlineData(365 + 365 + 365 + 365 + 366, "4 years, 11 months, 4 weeks, 2 days")]
3740
[InlineData(365 + 365 + 365 + 365 + 366 + 1, "5 years")]
3841
public void Year(int days, string expected)
3942
{
@@ -44,15 +47,15 @@ public void Year(int days, string expected)
4447
[Theory]
4548
[InlineData(30, "4 weeks, 2 days")]
4649
[InlineData(30 + 1, "1 month")]
47-
[InlineData(30 + 30, "1 month, 29 days")]
50+
[InlineData(30 + 30, "1 month, 4 weeks, 1 day")]
4851
[InlineData(30 + 30 + 1, "2 months")]
49-
[InlineData(30 + 30 + 31, "2 months, 30 days")]
52+
[InlineData(30 + 30 + 31, "2 months, 4 weeks, 2 days")]
5053
[InlineData(30 + 30 + 31 + 1, "3 months")]
51-
[InlineData(30 + 30 + 31 + 30, "3 months, 29 days")]
54+
[InlineData(30 + 30 + 31 + 30, "3 months, 4 weeks, 1 day")]
5255
[InlineData(30 + 30 + 31 + 30 + 1, "4 months")]
53-
[InlineData(30 + 30 + 31 + 30 + 31, "4 months, 30 days")]
56+
[InlineData(30 + 30 + 31 + 30 + 31, "4 months, 4 weeks, 2 days")]
5457
[InlineData(30 + 30 + 31 + 30 + 31 + 1, "5 months")]
55-
[InlineData(365, "11 months, 30 days")]
58+
[InlineData(365, "11 months, 4 weeks, 2 days")]
5659
[InlineData(366, "1 year")]
5760
public void Month(int days, string expected)
5861
{
@@ -433,5 +436,15 @@ public void CanSpecifyCultureExplicitly(int ms, int precision, string culture, s
433436
var actual = TimeSpan.FromMilliseconds(ms).Humanize(precision: precision, culture: new CultureInfo(culture), collectionSeparator: collectionSeparator);
434437
Assert.Equal(expected, actual);
435438
}
439+
440+
[Fact]
441+
//Fixes https://stackoverflow.com/questions/56550059/humanizer-months-weeks-days-hours
442+
public void MonthsAndWeeks()
443+
{
444+
var ts = new TimeSpan(109, 4, 0, 0, 0);
445+
var humanized = ts.Humanize(4, maxUnit: TimeUnit.Month);
446+
447+
Assert.Equal("3 months, 2 weeks, 3 days, 4 hours", humanized);
448+
}
436449
}
437450
}

src/Humanizer/TimeSpanHumanizeExtensions.cs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.Linq;
@@ -143,7 +143,14 @@ private static int GetSpecialCaseWeeksAsInteger(TimeSpan timespan, bool isTimeUn
143143
{
144144
return timespan.Days / _daysInAWeek;
145145
}
146-
return 0;
146+
else
147+
{
148+
var timespanRemaining = timespan - TimeSpan.FromDays(GetSpecialCaseYearAsInteger(timespan) * _daysInAYear)
149+
- TimeSpan.FromDays(
150+
GetSpecialCaseMonthAsInteger(timespan, false) * _daysInAMonth);
151+
152+
return timespanRemaining.Days / _daysInAWeek;
153+
}
147154
}
148155

149156
private static int GetSpecialCaseDaysAsInteger(TimeSpan timespan, bool isTimeUnitToGetTheMaximumTimeUnit)
@@ -152,12 +159,17 @@ private static int GetSpecialCaseDaysAsInteger(TimeSpan timespan, bool isTimeUni
152159
{
153160
return timespan.Days;
154161
}
155-
if (timespan.Days < _daysInAMonth)
162+
else
156163
{
157-
var remainingDays = timespan.Days % _daysInAWeek;
164+
var timespanRemaining = timespan - TimeSpan.FromDays(
165+
GetSpecialCaseYearAsInteger(timespan) * _daysInAYear)
166+
- TimeSpan.FromDays(
167+
GetSpecialCaseMonthAsInteger(timespan, false) * _daysInAMonth)
168+
- TimeSpan.FromDays(
169+
GetSpecialCaseWeeksAsInteger(timespan, false) * _daysInAWeek);
170+
var remainingDays = timespanRemaining.Days;
158171
return remainingDays;
159172
}
160-
return (int)(timespan.Days % _daysInAMonth);
161173
}
162174

163175
private static int GetNormalCaseTimeAsInteger(int timeNumberOfUnits, double totalTimeNumberOfUnits, bool isTimeUnitToGetTheMaximumTimeUnit)

0 commit comments

Comments
 (0)