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

Minimize verbosity of Timespan formatting. #571

Open
rlightner opened this issue Jun 30, 2016 · 26 comments · May be fixed by #1183
Open

Minimize verbosity of Timespan formatting. #571

rlightner opened this issue Jun 30, 2016 · 26 comments · May be fixed by #1183

Comments

@rlightner
Copy link

Is there a way to use duration abbreviations when Humanizing a TimeSpan? I'd like to use mins instead of minutes etc..

@darylbehrens
Copy link

darylbehrens commented Aug 3, 2016

@rlightner Can you please show a code example of what you are doing? Thank you.

@rlightner
Copy link
Author

@darylbehrens Who was that directed at?

@evansaa1

This comment was marked as off-topic.

@michal-ciechan
Copy link

I would like to use "m" instead of "mins or minutes"

1y, 2m, 4d, 20h, 59m, 12s

@michal-ciechan
Copy link

michal-ciechan commented Mar 13, 2017

I am thinking of adding the functionality of using short(er) variants.

e.g.

TimeSpan.FromSeconds().Humanize(short: true)

or

TimeSpan.FromSeconds().Humanize(format: TimeSpanFormat.Short)

possibly giving

public enum TimeSpanFormat 
{
    Normal,
    Short, // 1 yr, 2 mos, 2 days, 5 hrs, 56 mins, 12 secs  - Original request?
    Single, // 1y, 2m, 2d, 4h, 56m, 12s
}

I guess these could be as separate keys in the resources, with falling back to the previous if one is not found?

@erdmenchen
Copy link

This would be awesome to have for DateTimeOffset as well:
"23s ago" instead of "23 seconds ago"...

@odemeulder
Copy link

I would love to work on this issue. One question though, how would we deal with all the languages? Let's say we had a new parameter indicating the format, and the new key did not exist for a particular language. Would it revert to the default format?

@MaStr11
Copy link
Contributor

MaStr11 commented May 9, 2017

If you look at the current language support you will find 145 entries:

RessourceKey Value
DateHumanize_MultipleDaysAgo {0} days ago
DateHumanize_MultipleDaysAgo_Above20 {0} days ago
DateHumanize_MultipleDaysAgo_Dual {0} days ago
DateHumanize_MultipleDaysAgo_Plural {0} days ago
DateHumanize_MultipleDaysAgo_Singular {0} day ago
DateHumanize_MultipleDaysAgo_TrialQuadral {0} days ago
DateHumanize_MultipleDaysFromNow {0} days from now
DateHumanize_MultipleDaysFromNow_Dual {0} days from now
DateHumanize_MultipleDaysFromNow_Plural {0} days from now
DateHumanize_MultipleDaysFromNow_Singular {0} day from now
DateHumanize_MultipleDaysFromNow_TrialQuadral {0} days from now
DateHumanize_MultipleHoursAgo {0} hours ago
DateHumanize_MultipleHoursAgo_Above20 {0} hours ago
DateHumanize_MultipleHoursAgo_Dual {0} hours ago
DateHumanize_MultipleHoursAgo_DualTrialQuadral {0} hours ago
DateHumanize_MultipleHoursAgo_Plural {0} hours ago
DateHumanize_MultipleHoursAgo_Singular {0} hour ago
DateHumanize_MultipleHoursAgo_TrialQuadral {0} hours ago
DateHumanize_MultipleHoursFromNow {0} hours from now
DateHumanize_MultipleHoursFromNow_Dual {0} hours from now
DateHumanize_MultipleHoursFromNow_DualTrialQuadral {0} hours from now
DateHumanize_MultipleHoursFromNow_Plural {0} hours from now
DateHumanize_MultipleHoursFromNow_Singular {0} hour from now
DateHumanize_MultipleHoursFromNow_TrialQuadral {0} hours from now
DateHumanize_MultipleMinutesAgo {0} minutes ago
DateHumanize_MultipleMinutesAgo_Above20 {0} minutes ago
DateHumanize_MultipleMinutesAgo_Dual {0} minutes ago
DateHumanize_MultipleMinutesAgo_DualTrialQuadral {0} minutes ago
DateHumanize_MultipleMinutesAgo_Plural {0} minutes ago
DateHumanize_MultipleMinutesAgo_Singular {0} minute ago
DateHumanize_MultipleMinutesAgo_TrialQuadral {0} minutes ago
DateHumanize_MultipleMinutesFromNow {0} minutes from now
DateHumanize_MultipleMinutesFromNow_Dual {0} minutes from now
DateHumanize_MultipleMinutesFromNow_DualTrialQuadral {0} minutes from now
DateHumanize_MultipleMinutesFromNow_Plural {0} minutes from now
DateHumanize_MultipleMinutesFromNow_Singular {0} minute from now
DateHumanize_MultipleMinutesFromNow_TrialQuadral {0} minutes from now
DateHumanize_MultipleMonthsAgo {0} months ago
DateHumanize_MultipleMonthsAgo_Dual {0} months ago
DateHumanize_MultipleMonthsAgo_DualTrialQuadral {0} months ago
DateHumanize_MultipleMonthsAgo_Plural {0} months ago
DateHumanize_MultipleMonthsAgo_Singular {0} month ago
DateHumanize_MultipleMonthsAgo_TrialQuadral {0} months ago
DateHumanize_MultipleMonthsFromNow {0} months from now
DateHumanize_MultipleMonthsFromNow_Dual {0} months from now
DateHumanize_MultipleMonthsFromNow_DualTrialQuadral {0} months from now
DateHumanize_MultipleMonthsFromNow_Plural {0} months from now
DateHumanize_MultipleMonthsFromNow_Singular {0} month from now
DateHumanize_MultipleMonthsFromNow_TrialQuadral {0} months from now
DateHumanize_MultipleSecondsAgo {0} seconds ago
DateHumanize_MultipleSecondsAgo_Above20 {0} seconds ago
DateHumanize_MultipleSecondsAgo_Dual {0} seconds ago
DateHumanize_MultipleSecondsAgo_DualTrialQuadral {0} seconds ago
DateHumanize_MultipleSecondsAgo_Plural {0} seconds ago
DateHumanize_MultipleSecondsAgo_Singular {0} second ago
DateHumanize_MultipleSecondsAgo_TrialQuadral {0} seconds ago
DateHumanize_MultipleSecondsFromNow {0} seconds from now
DateHumanize_MultipleSecondsFromNow_Dual {0} seconds from now
DateHumanize_MultipleSecondsFromNow_DualTrialQuadral {0} seconds from now
DateHumanize_MultipleSecondsFromNow_Plural {0} seconds from now
DateHumanize_MultipleSecondsFromNow_Singular {0} second from now
DateHumanize_MultipleSecondsFromNow_TrialQuadral {0} seconds from now
DateHumanize_MultipleYearsAgo {0} years ago
DateHumanize_MultipleYearsAgo_Above20 {0} years ago
DateHumanize_MultipleYearsAgo_Dual {0} years ago
DateHumanize_MultipleYearsAgo_DualTrialQuadral {0} years from ago
DateHumanize_MultipleYearsAgo_Plural {0} years ago
DateHumanize_MultipleYearsAgo_Singular {0} year ago
DateHumanize_MultipleYearsAgo_TrialQuadral {0} years ago
DateHumanize_MultipleYearsFromNow {0} years from now
DateHumanize_MultipleYearsFromNow_Dual {0} years from now
DateHumanize_MultipleYearsFromNow_DualTrialQuadral {0} years from now
DateHumanize_MultipleYearsFromNow_Plural {0} years from now
DateHumanize_MultipleYearsFromNow_Singular {0} year from now
DateHumanize_MultipleYearsFromNow_TrialQuadral {0} years from now
DateHumanize_Never never
DateHumanize_Now now
DateHumanize_SingleDayAgo yesterday
DateHumanize_SingleDayFromNow tomorrow
DateHumanize_SingleHourAgo an hour ago
DateHumanize_SingleHourFromNow an hour from now
DateHumanize_SingleMinuteAgo a minute ago
DateHumanize_SingleMinuteFromNow a minute from now
DateHumanize_SingleMonthAgo one month ago
DateHumanize_SingleMonthFromNow one month from now
DateHumanize_SingleSecondAgo one second ago
DateHumanize_SingleSecondFromNow one second from now
DateHumanize_SingleYearAgo one year ago
DateHumanize_SingleYearFromNow one year from now
TimeSpanHumanize_MultipleDays {0} days
TimeSpanHumanize_MultipleDays_Dual {0} days
TimeSpanHumanize_MultipleDays_Plural {0} days
TimeSpanHumanize_MultipleDays_Singular {0} day
TimeSpanHumanize_MultipleDays_TrialQuadral {0} days
TimeSpanHumanize_MultipleHours {0} hours
TimeSpanHumanize_MultipleHours_Dual {0} hours
TimeSpanHumanize_MultipleHours_DualTrialQuadral {0} hours
TimeSpanHumanize_MultipleHours_Plural {0} hours
TimeSpanHumanize_MultipleHours_Singular {0} hour
TimeSpanHumanize_MultipleHours_TrialQuadral {0} hours
TimeSpanHumanize_MultipleMilliseconds {0} milliseconds
TimeSpanHumanize_MultipleMilliseconds_Dual {0} milliseconds
TimeSpanHumanize_MultipleMilliseconds_DualTrialQuadral {0} milliseconds
TimeSpanHumanize_MultipleMilliseconds_Plural {0} milliseconds
TimeSpanHumanize_MultipleMilliseconds_Singular {0} millisecond
TimeSpanHumanize_MultipleMilliseconds_TrialQuadral {0} milliseconds
TimeSpanHumanize_MultipleMinutes {0} minutes
TimeSpanHumanize_MultipleMinutes_Dual {0} minutes
TimeSpanHumanize_MultipleMinutes_DualTrialQuadral {0} minutes
TimeSpanHumanize_MultipleMinutes_Plural {0} minutes
TimeSpanHumanize_MultipleMinutes_Singular {0} minute
TimeSpanHumanize_MultipleMinutes_TrialQuadral {0} minutes
TimeSpanHumanize_MultipleMonths {0} months
TimeSpanHumanize_MultipleMonths_Dual {0} months
TimeSpanHumanize_MultipleMonths_DualTrialQuadral {0} months
TimeSpanHumanize_MultipleMonths_Plural {0} months
TimeSpanHumanize_MultipleMonths_Singular {0} months
TimeSpanHumanize_MultipleMonths_TrialQuadral {0} months
TimeSpanHumanize_MultipleSeconds {0} seconds
TimeSpanHumanize_MultipleSeconds_Dual {0} seconds
TimeSpanHumanize_MultipleSeconds_DualTrialQuadral {0} seconds
TimeSpanHumanize_MultipleSeconds_Plural {0} seconds
TimeSpanHumanize_MultipleSeconds_Singular {0} second
TimeSpanHumanize_MultipleSeconds_TrialQuadral {0} seconds
TimeSpanHumanize_MultipleWeeks {0} weeks
TimeSpanHumanize_MultipleWeeks_Dual {0} weeks
TimeSpanHumanize_MultipleWeeks_DualTrialQuadral {0} weeks
TimeSpanHumanize_MultipleWeeks_Plural {0} weeks
TimeSpanHumanize_MultipleWeeks_Singular {0} week
TimeSpanHumanize_MultipleWeeks_TrialQuadral {0} weeks
TimeSpanHumanize_MultipleYears {0} years
TimeSpanHumanize_MultipleYears_Dual {0} years
TimeSpanHumanize_MultipleYears_DualTrialQuadral {0} years
TimeSpanHumanize_MultipleYears_Plural {0} years
TimeSpanHumanize_MultipleYears_Singular {0} years
TimeSpanHumanize_MultipleYears_TrialQuadral {0} years
TimeSpanHumanize_SingleDay 1 day
TimeSpanHumanize_SingleHour 1 hour
TimeSpanHumanize_SingleMillisecond 1 millisecond
TimeSpanHumanize_SingleMinute 1 minute
TimeSpanHumanize_SingleMonth 1 month
TimeSpanHumanize_SingleSecond 1 second
TimeSpanHumanize_SingleWeek 1 week
TimeSpanHumanize_SingleYear 1 year
TimeSpanHumanize_Zero no time

All of these have to be shortened so there will be 145 entries for TimeSpanFormat.Short and 145 entries for TimeSpanFormat.Single. This will not scale for 50+ languages currently supported (To be fair: Actually for most languages it is sufficient to translate 45 entries).

If you have a closer look it is possible to get rid of all the DateHumanize_ entries because those are TimeSpanHumanize_ entries with ago or from now added (other languages prefix those). Therefore it would be sufficient to have DateHumanize_FromNow_Format -> {0} from now and DateHumanize_Ago_Format -> {0} ago. This would also help to implement #498 (Currently it is not possible to output 'You are 40 years old.' based on a birth-date and a reference date).

I would suggest to discuss the design of the localization before we add a few 100 more entries to the resource files.

@dotnetwise
Copy link

One year passed, nothing moved on (about this).
Even with 50+ languages to translate in, is far better than 0 support for it.

Any plan to actually support this?

@NageshAndani
Copy link

I would like to work on this issue. Can you please assign it to me?

@clairernovotny
Copy link
Member

It's yours.... GitHub only allows assignments to organization members, but anyone looking should see this thread.

@ZacharyCouchman
Copy link

I've started working on this issue. I like @michal-ciechan's idea of introducing a format enum

@AKTheKnight
Copy link
Contributor

Hey @ZacharyCouchman did you get anywhere on this by any chance?

@Janek91
Copy link

Janek91 commented Mar 17, 2020

Any news about it?

@tynor88
Copy link

tynor88 commented Mar 19, 2020

This would be awesome indeed!

@chrisjshields

This comment was marked as off-topic.

@mr-aboutin
Copy link
Contributor

This looks like the same issue was duplicated in #969 and I made a pull request for some of the abbreviation in #990

@prince272

This comment was marked as off-topic.

@clairernovotny
Copy link
Member

I'll be happy to take a PR that adds support for this feature if someone wants to take it on.

@prince272
Copy link

prince272 commented Jan 26, 2022

What happened to this commit? 8373d2f

@clairernovotny
Copy link
Member

clairernovotny commented Jan 26, 2022

I have no idea and haven't looked. All I can see is that the PR looked like it needed fixing: #990. If someone wants to finish it off, that'd be great!

@prince272
Copy link

Oh okay.

@petrkoutnycz
Copy link

It's real pity it has not been implemented yet, not even for English :-(

@derekoakley
Copy link

It would be amazing if this could be part of the v3 milestone somehow!

@dpaulino
Copy link

Would love to see this in the near future, as well.

@simonziegler
Copy link

simonziegler commented Mar 4, 2024

I just did this for my purposes with some regex. There's a sample program below that I'd love to claim credit for, but that goes to Copilot!

using Humanizer;
using System.Globalization;
using System.Text.RegularExpressions;

TimeSpan t = new DateTime(2024, 3, 25) - new DateTime(2024, 2, 13);

CultureInfo culture = new("de-DE");

var longString = t.Humanize(3, culture, maxUnit: Humanizer.Localisation.TimeUnit.Month);

string pattern = @"(\d+)\s+(\w)\w*";

string shortString = Regex.Replace(longString, pattern, ReplaceWithFirstLetter);
Console.WriteLine("Long timespan:  " + longString);
Console.WriteLine("Short timespan: " + shortString);

static string ReplaceWithFirstLetter(Match match)
{
    var digits = match.Groups[1].Value;
    var firstLetter = match.Groups[2].Value;
    return $"{digits}{firstLetter}";
}

And here's the output:

Long timespan:  1 Monat, 10 Tage
Short timespan: 1M, 10T

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.