NuGet Package of the Week: Humanizer makes .NET data types more human
The .NET BCL (Base Class Library) moves too slow, IMHO. That's why NuGet and NuGet packages are so nice. It's a joy to find a "rightly sized" library like NodaTime, for example. It's a better date and time API for .NET. Microsoft should just use it, it's lovely.
Another nicely-sized Open Source library, and the focus for today's blog post, is Humanizer from http://humanizr.net. They say "Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities" and it does just that.
It's a lovely joy of a library and you should check it out. Just make yourself a console app now and install-package Humanizer, and explore.
Note: Be sure to check out all the NuGet packages of the week! There's more!
The word "Humanize" evokes, for me, a feeling of making something simpler, more accessible, more useful, more fluent, more flexible.
Here's some great examples of problems that Humanizer solves.
First, Humanzer has a LOT of extension methods to the string type. If you've got a funky string, it will turn it into as close to a normally-cased sentence as possible. This is even more useful if you're using BDD frameworks like BDDfy.
"PascalCaseInputStringIsTurnedIntoSentence".Humanize() => "Pascal case input string is turned into sentence"
"Underscored_input_string_is_turned_into_sentence".Humanize() => "Underscored input string is turned into sentence"
// acronyms are left intact
"HTML".Humanize() => "HTML"
"Can_return_title_Case".Humanize(LetterCasing.Title) => "Can Return Title Case"
"CanReturnLowerCase".Humanize(LetterCasing.LowerCase) => "can return lower case"
There's dozens of great string methods, but it's the DateTime extension methods that really shine. These will feel familiar to Rails developers and Twitter users.
DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"
DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"
DateTime.UtcNow.AddHours(30).Humanize() => "tomorrow"
DateTime.UtcNow.AddHours(2).Humanize() => "2 hours from now"
TimeSpan.FromMilliseconds(1299630020).Humanize() => "2 weeks"
TimeSpan.FromMilliseconds(1299630020).Humanize(3) => "2 weeks, 1 day, 1 hour"
Pluralization libraries are always fun, as I've blogged before and Humanizer doesn't disappoint. You can pluralize and singularlize strings, but the "To Quantity" methods are fantastic, doing exactly what you'd expect, even if you do something odd:
"men".ToQuantity(2) => "2 men"
"process".ToQuantity(2) => "2 processes"
"process".ToQuantity(1) => "1 process"
"processes".ToQuantity(1) => "1 process"
"case".ToQuantity(0) => "0 cases"
"case".ToQuantity(1) => "1 case"
Even as words!
"case".ToQuantity(5, ShowQuantityAs.Words) => "five cases"
The Number to Words family of methods go even further:
3501.ToWords() => "three thousand five hundred and one"
121.ToOrdinalWords() => "hundred and twenty first"
8.ToRoman() => "VIII"
We've all written a truncate method to take a long string and add "..." at the end.
"Long text to truncate".Truncate(6, Truncator.FixedNumberOfCharacters) => "Long t…"
"Long text to truncate".Truncate(6, "---", Truncator.FixedNumberOfCharacters) => "Lon---"
I'm just scratching the surface of Humanizer, going through it's Getting Started. There's also samples where you can plug it into your own frameworks or deep within ASP.NET MVC and humanize enums, type names, and properties as a way to keep your code DRY.
Humanizer is even starting to support localization to non-English languages, and helping with the localization of Humanizer is a GREAT OPPORTUNITY if you're looking to get into Open Source as well as learning Git and GitHub Flow.
I like open source libraries like this that look like the code we've all written before...except tested and complete. ;) We've all written utilities like this, except as one-of functions. I look forward to NOT writing methods like this in the future, and instead using libraries like Humanizer. I fully plan to use this library in my next project (a startup I'm working on.)
Go take a look at Humanizer and thank the author on Twitter while you're at it!
Sponsor: Big thanks to Novalys for sponsoring the blog feed this week! Check out their security solution that combines authentication and user permissions. Secure access to features and data in most applications & architectures (.NET, Java, C++, SaaS, Web SSO, Cloud...). Try Visual Guard for FREE.
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
Looks like you pasted the wrong thing into the NodaTime link in the first paragraph. :-)
I've needed at least a couple of these functions in the past for sure...
Quick typo near the end ... "one-off" rather than "one-of" (Sorry, nit-picking!)
the link is in the post.
Your name sounds dutch, so: https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer/Properties/Resources.nl.resx
I cannot take credit for the whole thing: there are 26 contributors who've contributed a lot of goodness to the framework. Oh and while we're at it I am very open to feature requests or even better pull requests :p
There are quite a few active contributors on Humanizer who're always happy to lend a hand or guide you, should you need that. Please check out the contribution guide where I explain how you can contribute and how your code is reviewed.
@JP - thanks for the correct and prompt response.
@Jan - as JP mentioned there are already quite a lot of localisations in there; but if one is missing it's very easy to add it in. After this post I've received a PR for Swedish translation and two PRs for fixing and completing Norwegian and Finnish translations :) Here is a guide on how you can create a new translation.
P.S. I hope I am not double posting this. The first submission kinda evaporated into the thin air.
I appreciate your Dev Tool List for years.
Now, the comments to your last tools post are closed. It's a pity, because I'd like to add something. Zip is a much faster format than 7z. I've done a lot of measurements and posted about it.
I hope you can put this comment to your Dev Tool List.
Best Regards, Andreas
1) I should feel honored.
2) Stuff I wrote even a mere three years ago could benefit from some serious refactoring.
Not to use as an excuse; but I receive a lot of PRs on Humanizer which is already very time consuming to review/fix/rebase/release and this is going to make it harder. So this makes me wonder, how do OSS leaders deal with this?
Why do this:
when you can have an extension method on Integer which could do this:
Just a thought.
There's some goodness for TimeSpan
2.Milliseconds() => TimeSpan.FromMilliseconds(2)
2.Seconds() => TimeSpan.FromSeconds(2)
2.Minutes() => TimeSpan.FromMinutes(2)
2.Hours() => TimeSpan.FromHours(2)
2.Days() => TimeSpan.FromDays(2)
2.Weeks() => TimeSpan.FromDays(14)
In.TheYear(2010) // Returns the first of January of 2010
In.January // Returns 1st of January of the current year
In.FebruaryOf(2009) // Returns 1st of February of 2009
In.One.Second // DateTime.UtcNow.AddSeconds(1)
In.Three.Minutes // With corresponding From method
In.Three.Hours // With corresponding From method
In.Three.Days // With corresponding From method
In.Three.Weeks // With corresponding From method
In.Three.Months // With corresponding From method
In.Three.Years // With corresponding From method
On.January.The4th // Returns 4th of January of the current year
On.February.The(12) // Returns 12th of Feb of the current year
I've commented on the github page as per your tweet to me.
You're doing great work with Humanizer (and thank you for not calling it Humnizr or some such social-networky name!) and I appreciate your attention to all its details.
@Adam - there are a few `Dehumanize` methods; e.g. Dehumanize string and enums. Please check out the project home page for them. WRT dehumanizing date and times, that's a bit impractical as date humanize is a lossy transformation. You can see more details here.
ps: I'll try NodaTime as well ;)
Comments are closed.