humanizr / humanizer Goto Github PK
View Code? Open in Web Editor NEWHumanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities
License: Other
Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities
License: Other
In Date.Humanize
we have "yesterday" for a day ago and "one year ago" for "last year". How would everyone feel about changing it to "last year"? It is more humanized and is more consistent with the "yesterday" logic!
Hello,
maybe we need a new better continuous integration system ?
@hmemcpy raised a valid concern:
how can I prevent from copying all the language-specific resource to the output dir with Humanizer? Don't want 'em :)
NuGet supports two localization approach: single & satellite localized packages. Humanizer currently uses single localized package & I don't think it's possible to achieve this in this mode.
I think it's a good idea to switch to satellite packages even though it's a breaking change for this and other benefits.
To Do:
The idea is to leave last word unbreaked.
"Text with more characters than truncate length"
.Truncate(12, "...", Truncator.NumberOfCharacters /* Name TBD */);
=> "Text with more..."
or
=>"Text with..."
I'm not sure about the name of strategy. Also I'm not sure what to do with long words.
In January 2014, Humanizer trended up on GitHub to become the C# repository of the week, ranked over SignalR, ServiceStack, Nancy, ScriptCS and WebEssentials :)
Thanks a lot for your support.
P.S. GitHub really needs an announcement feature for repositories. In the absence of that I label this as Announcement.
As far as I can tell all Localisation methods are failing in Windows Store apps. The root causes appears to be the loading for the resource strings.
All calls to DateTime.Humanize and TimeSpan.Humanize are throwing an ArgumentNullException in String.Format.
In the below example the result is null rather than the resource string.
var resource = Humanizer.Localisation.Resources.GetResource(Humanizer.Localisation.ResourceKeys.TimeSpanHumanize.MultipleDays);
It's a pain to have to cast back to the target enum every time.
Currently calling Singularize
on a singular word returns null or an incorrect value (e.g. "Process".Singularize() => "Proces"
. Same goes for Pluralize
on a plural word (e.g. "men".Pluralize() => "mens")
Ideally we need to implement IsPlural
and/or IsSingular
extension methods. This way we can fix this issue using the methods and the users of the framework can use the new methods to check a word without having to call Singularize
or Pluralize
on it.
I am trying to add Slovak localization, that requires a separate Formatter. I have written unit tests but when I run them, some of them are one-off.
Consider
[Theory]
[InlineData(1, "o hodinu")]
[InlineData(2, "o 2 hodiny")]
[InlineData(3, "o 3 hodiny")]
[InlineData(4, "o 4 hodiny")]
[InlineData(5, "o 5 hodín")]
[InlineData(6, "o 6 hodín")]
[InlineData(10, "o 10 hodín")]
public void NHoursFromNow(int number, string expected)
{
var humanize = DateTime.UtcNow.AddHours(number).Humanize();
Assert.Equal(expected, humanize);
}
When I run the tests, I get "o 9 hodín" for the last case testing "o 10 hodín". I guess the Humanize method got called with 9 instead of 10.
Am I missing something in writting the tests?
Copied @waheedsayed's thought over from #70:
I'm thinking to do the following
Split it into two formatters: DateTimeFormatter & TimeSpanFormatter
Shorten names by removing prefixes DateHumaniz_xxx & TimeSpanHumanize_xxx
On the project home page, the browser renders this text:
You may find an Asp.Net MVC sample [in the code][5] that does...
We need reference 5.
"request".ToQuantity(0) => "0 requests"
"request".ToQuantity(1) => "1 request"
"request".ToQuantity(2) => "2 requests"
Heaps of useful discussion around this issue and the method naming can be found at #25
I could use a non-generic EnumDehumanizeExtensions.DehumanizeTo for when the enum type isn't known at compile time.
I wrote my own which I use in my HumanizedEnumConverter:
https://rapiddevbookcode.codeplex.com/SourceControl/latest#LLBL Pro v4.1/AW.Helper/TypeConverters/HumanizedEnumConverter.cs
e.g.
private static Enum DehumanizeTo(string input, Type enumType)
{
var values = Enum.GetValues(enumType);
foreach (var value in values)
{
var enumValue = value as Enum;
if (enumValue == null)
return null;
if (string.Equals(enumValue.Humanize(), input, StringComparison.OrdinalIgnoreCase))
return enumValue;
}
return null;
}
When i do DateTime.Now.AddDays(-1).Humanize() i get result as "23 hours ago" and not as yesterday which i have expected.
Am i doing anything wrong?
Also DateTime.Now.AddDays(1).Humanize() gives me result as not yet.
[Fact]
public void ElevenDays()
{
var elevenDays = TimeSpan.FromDays(11);
var actual = elevenDays.Humanize();
Assert.Equal("11 days", actual); //actual is (1 week) while I expect (11 days)
}
In my mindset I expect:
7 days -> 1 week
14 days -> 2 weeks
11 days -> 11 days
In Hebrew, there are both masculine and feminine forms of numbers, e.g. 1 can be either אחת ("achat", feminine) or אחד ("echad", masculine), depending on the preceding or following word.
I wonder how to address this issue in implementing ToWords() Hebrew extension? An additional overload, accepting this sounds reasonable, but not all languages have this...
Ideas?
=> input as bytes(long) => output as readable string(eg. 1.2 MB)
IndefiniteArticle
could be an option in a few methods; e.g. ToQuatity
, ToWords
etc.
The documentation says dehumanization of dates is not reversible, but is that only because a phrase like "yesterday" is relative to some unknown reference point?
What if the API included a method like "yesterday".DehumanizeRelativeTo(DateTime.UtcNow)
that calculated "yesterday" from the perspective of the current time? It would be really cool to be able to turn the string "set an alarm for tomorrow at two thirty" into a command + datetime-relative-to-now using the Humanize library (rather than rolling your own). I assume this idea has been visited before, were there any specific challenges that can't be solved with an explicit reference date?
The built in .NET PluralizationService has more work done in correctly pluralizing most of English. Please consider using this as the service behind the Pluralize feature of Humanizer.
I realize it is in an assembly you probably do not want to require as a dependency, but perhaps some notes can be taken from it.
Not sure how involved this is going to be; but this would be a nice addition if there is a relatively simple light solution.
Thoughts?
Great work with this utility library - very useful. A few things to keep you out of hot water that I might suggest is:
Just a few thoughts :).
"request".ToQuantity(2)
returns "2 requests"
; but "men".ToQuantity(2)
returns "2 mens"
and "processes".ToQuantity(1)
returns "1 processes".
To fix this I think we need to first fix issue #38 .
I would expect this:
var timespan = TimeSpan.FromDays(2) + TimeSpan.FromHours(3) + TimeSpan.FromMinutes(5);
Assert.That(timespan.Humanize(), Is.EqualTo("2 days, 3 hours, 5 minutes"));
But it seems to come back with 2 days
currently.
This is to prevent situations like #153
DateTime.Humanize
has gotten a bit complex over time. It needs to be refactored.
It gives صفر cases instead of zero cases and واحد case instead of one case ?
There is 15 other test fail, namely ToOrdinalWords and DateHumanizeTests.
ToOrdinalWords صفرth is wrong and does not exist in Arabic ?
Only happen on my computer because my windows region and language is set to Arabic.
Jesse Slicer commented on Scott Hanselman's post about Humanizer saying Roman
feature is a copy of his work and the contributor failed to acknowledge that in the code, which is not nice. Need to fix this ASAP.
Hello,
I tested Humanizer on an ASP.NET MVC CMS project and I have a few suggestions:
1 - Add a HumanizerConfiguration for startup
This would be used to define, for example, custom translations.
The translations could be use a Fluent API.
This would be more flexible then having Resource files built in Humanizer.
2 - Add the option for enum humanizer to allow a different attribute than Description.
Again, this could be applied in HumanizerConfiguration.
3 - Add extensions points to humanizer ...
I could create an extension to do some type of conversion ...
This way people could start to create humanizer "plugins" and share.
What do you think? Just some ideas from my short experience with Humanizer.
Thank You,
Miguel
I suggest to make Configurator.FormatterFactories
public or add methods to add and remove factories from configuration. It can be useful if someone wants to use custom formatter which is, for example, not ready to be included to a library, etc.
DateTimeHumanize tests are created by contributors and over the time the coding style has shifted and now the old code are inconsistent with the rest of the tests. Test method names, testing patterns etc should be made consistent.
If an enum is annotated with a descendants of DescriptionAttribute that annotation doesn't get honoured by EnumHumanizeExtensions.Humanize, IOW, it gets ignored.
Example of a DescriptionAttribute descendant:
http://www.codeproject.com/Articles/29495/Binding-and-Using-Friendly-Enums-in-WPF
What do you guys/gals think about the following:
var longPieceOfText = "This is some text that's too large to display into a column in a table (HTML), but should present nicely when truncated to a certain length";
Assert.That(longPieceOfText.TrimTo(10), Is.EqualTo("This is s…"));
Possible variations include trimming to the last word
Assert.That(longPieceOfText.TrimTo(10,Option.RespectWords), Is.EqualTo("This is some …"));
Trimming to the last word but respecting the length as absolute maximum
Assert.That(longPieceOfText.TrimTo(10,Option.RespectWords | ,Option.ConsiderLengthAbsolute), Is.EqualTo("This is …"));
See also https://github.com/HubSpot/humanize#truncate
If it's desirable I might start hacking on a PR this week...
Humanizer started out with three very simple methods all named Humanize
. So I described it as "a framework that turns your normal strings, type names, enums and DateTime into a human friendly format".
Things have changed a lot since and I am looking for a better elevator pitch that tells the story nicely and is less than 10 sentences.
Your help is much appreciated :)
Provide a mechanism to optionally omit the number from the ToQuantity
result. For example, "case".ToQuantity(5, QuantityOptions.OmitNumber)
would be "cases", where OmitNumber
would be a Flags
enum.
Look at http://www.unicode.org/cldr/charts/25/by_type/units.duration.html
you can see almost 700 culture resources for TimeSpan localization. We can fill in missing localization from this website.
How to display lists in various languages and cultures http://www.unicode.org/cldr/charts/25/by_type/miscellaneous.displaying_lists.html
and much more http://www.unicode.org/cldr/charts/25/by_type/index.html
Looks like dates are all in the past.
How about future dates - should use the same breakdowns but be "from now" instead.
Also, maybe +/- some threshold, there could be a "now"
Hello,
I got an idea to make percentage extensions
for example :
public static decimal PercentageOf(this double number, int percent) {
return (decimal)(number * percent / 100);
}
Last night I have also randomly failing tests which used DateHumanize.Verify
.
I had no time to look deeper, but the problem seems be that Humanize
uses DateTime.UtcNow
to determine current time.
Maybe we should add an interface for the clock, so we get reliable time in tests.
This approach also followed by the NodaTime library.
Hey guys, seems there is an issue with a nuget package. I can't install it through the package manager (package not found) and https://www.nuget.org/packages/Humanizer returns "not found" as well.
e.g. (55 days).Humanize(precision:5) => "2 months" (instead of one month)
We also need to apply a sensible default based on each unit; e.g.
Also perhaps these defaults should be lower for singular units; e.g. 25 days shouldn't report as one month; but 29 days perhaps could report as one month while 55 days reports as 2 months! A bit unsure about this as it might get a bit confusing.
Either way this is a breaking change and as such set for V2.
It would be handy to have an option to do something like
1 -> First
2 -> Second
3 -> Third
Hopefully theres not something already to do this, couldnt see anything.
On the post where I announce V1 Lenny Bacon mentioned using Hyphenate
instead of Dasherize
makes more sense.
We cannot remove Dasherize
but we could add Hyphenate
method that calls Dasherize
.
Hi,
I'm observing the above exception running Humanizer 1.11.3.0 on a production box with IIS6/.Net 4 / ASP.Net MVC 3.
Found a similar issue reported with AutoMapper (AutoMapper/AutoMapper#383) and wondering whether it could be the same root cause.
Complete stack trace follows;
[FileLoadException: Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)]
Humanizer.TimeSpanHumanizeExtensions.Humanize(TimeSpan timeSpan, Int32 precision) +0
BHP.ROS.Statusboard.DAL.Ampla.Dtos.DowntimeDto.get_DurationText() +177
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) +0
System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) +152
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) +393
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +38
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35
System.Web.Script.Serialization.JavaScriptSerializer.SerializeCustomObject(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +763
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1692
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +146
System.Web.Script.Serialization.JavaScriptSerializer.SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +182
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1647
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +146
System.Web.Script.Serialization.JavaScriptSerializer.SerializeDictionary(IDictionary o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +663
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +1576
System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat) +146
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat) +117
System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context) +280
System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +33
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func1 continuation) +784900 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList
1 filters, ActionResult actionResult) +265
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +784976
System.Web.Mvc.Controller.ExecuteCore() +159
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +335
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +62
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +20
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +54
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +453
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +371
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.