Humanizer
Humanizer copied to clipboard
[Feature Request] TimeSpan.Dehumanize()
Yes, I know there's been some lengthy discussion about dehumanizing dates (#112). And the readme even states:
No dehumanization for dates as
Humanizeis a lossy transformation and the human friendly date is not reversible"
There's also already a couple of libraries that deal with ambiguous expressions such as "yesterday", "3 weeks ago", and "7 hours before tomorrow at midnight". e.g. nChronic and Microsoft LUIS.
However, I can't see any discussion about dehumanizing TimeSpans, which are much more straight forward. Even if the main focus here is on humanizing rather than the reverse, this kind of thing would be well suited to this library
TimeSpan
TimeSpans are much less ambiguous than dates. There also don't seem to be many other libraries that deal with them well. Here's some basic examples / semi-pseudocode tests for a TimeSpan dehumanizer:
var timeTest = new TimeSpan(3, 18, 0);
Assert.Equals(TimeSpan.Dehumanize("three hours and eighteen minutes"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3 hours, 18 minutes"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3:18 hours"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3h18m"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3h 18m"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3.3hrs"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3:18:00"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("3:18"), timeTest);
Assert.Equals(TimeSpan.Dehumanize("18:01", expectedUnits:minutes), new TimeSpan(0, 18, 01));
I think this kind of thing would be fairly straight forward and without ambiguity.
The other libraries I've found that deal with dehumanizing TimeSpans are:
- Microsoft LUIS, e.g.
builtin.datetimeV2.durationbut it seems like it's overly complex and I'm guessing it's not open source. Also seems more focused on speech than text. - Exceptionless.DateTimeExtensions (Apache 2.0 licensed) has a parser that works as following:
TimeSpan oneHour = TimeUnit.Parse("3h");But would fail on all of the example strings I've given above as they are "complex".
TL;DR: Humanizer would be a good library to add a TimeSpan Dehumanizer to. I could be wrong, but I can't see anything overly complicated about it (unlike dehumanizing TimeDate text), as long as you stay away from accepting highly ambiguous inputs like "2 months" and stick to making it work as would be expected. I don't know much about what sort of things might trip up localization efforts though, but making it part of Humanizer would give a good chance for localization to occur.
I haven't (yet) poked around with the inner workers of Humanizer's parsers to see how easy it might be to add something like this, but thought I'd put it out there to see what interest was like.
I'm curious about what context you would see this being useful?
@onovotny My use case is a Discord (chat) bot which can act as a timer for "writing sprints" (a glorified 5 to 45 minute timer). So it accepts commands from members of chat.
Examples:
!sprint 15
Run a timer for 15 minutes.
!sprint 1000s
Run a timer for 1000 seconds.

This works here via DateTimeExtensions (mentioned in OP).
Ideally though...
But ideally a TimeSpan Dehumanizer would accept more arbitrary input. (These all fail to be parsed with DateTimeExtensions)
!sprint 12m 30s
This is a "complex" example (contains two units).
!sprint 0.25 hrs
This fails for multiple reasons: floating point, space, and odd spelling of hours. But shouldn't be difficult to make a dehumanizer for.
!sprint 15:10
Correctly treated as 15:10:00 (15h 10m) by built-in TimeSpan.Parse(), however an ideal parser should optionally treat it as 00:15:10 (15m 10s) when so configured.
!sprint twenty minutes
I was thinking Humanizer could already roundtrip numbers-to-words, but I just realized it only does this for Roman numerals, so maybe forget about this for now.
Conclusion
It's not 100% required feature, but I was surprised that there wasn't a library that enabled this kind of TimeSpan text parsing already (that I can find)
So basically, the use case is for entering a length of time for a timer where only text input is available, and the users are generally not be technical and have a low tolerance for failure (every failed attempt is seen by all members of the chat). Also, everyone likes a bot that can handle whatever is thrown at it.
More generally, I'd imagine this sort of function would also be useful anywhere users need to enter a time period as text, including: web forms, command line arguments, unit conversion calculators, text-based bots, and intelligent personal assistant services.
Edit: or it could be used in some hyper-advanced futuristic kid-friendly intellisense (excuse the crude mockup):

I will +1 this feature, for nearly the exact same use-case (Discord Bot)
However, I will also note, The discord.net library already has built in support for this, using the TimeSpan type converter. https://github.com/RogueException/Discord.Net
https://discord.foxbot.me/docs/guides/commands/commands.html#type-readers
Specific type read module:
https://github.com/RogueException/Discord.Net/blob/dev/src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs
I had a go at creating this a while ago but never got around to polishing it up to share. I'll upload it as a separate github project when I get a chance. It allows inputs like "3m20s" or "3 min 20.5secs" or "3:00:10" etc and most of the examples from above. (It does not accept word input like "three hours and eighteen minutes" though)
I didn't know about Discord.Net's parser. I'll put in some tests to check mine is compatible with everything it accepts too.
I'll try to upload it during the week.
I created a pull request for discord.net's version to fall back and use the built in parse method which helps alot.
It's not perfect, but, it understands... 1:10:00, 6d, 10m, 3s, etc....
On Sat, Aug 25, 2018, 6:26 AM Peter Halasz [email protected] wrote:
I had a go at creating this a while ago but never got around to polishing it up to share. I'll upload it as a separate github project when I get a chance. It allows inputs like "3m20s" or "3 min 20.5secs" or "3:00:10" etc.
I didn't know about Discord.Net's parser. I'll put in some tests to check mine is compatible with everything it accepts too.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Humanizr/Humanizer/issues/691#issuecomment-415962811, or mute the thread https://github.com/notifications/unsubscribe-auth/AFBNjxLCSwVA-JiqkGi7cdInXgiu35Ugks5uUTRngaJpZM4SX1Vi .
https://github.com/RogueException/Discord.Net/pull/1131
So, to summarize, the discord.net version, will soon just be mostly utilizing the builtin timespan.parse methods.
It would be really great for humanizer to support this feature!
Okay, here's my TimeSpanParser:
https://github.com/quole/TimeSpanParser
It doesn't parse "three hours and eighteen minutes" but it will do every other example.
I'd like to see something like this as well... My use case is the following;
I'm trying to achieve user friendly configuration file for one of my app's timer based features. I was already using Humanizer to save a default in the format "x minutes, y seconds", by the time I noticed there's no Dehumanize for those values. One would expect something at least for this default format. 😢
I support this as well, my use case is configuration of an application. As a TimeSpan cannot properly and reliable contain a span of months, but a string like "3 months" can, I would like to request this as a feature - together with a starting point from a given date. In that case you can correctly "dehumanize" the string "3 months" to a specific amount of days.
I have a similar need for configuration files.
Instead of
timeout: 00:00:00.050
I could use
timeout: 50ms
or
timeout: 50 milliseconds
I believe HomeAssistant uses a similar format for user-configurable time intervals.
@fdcastel TimeSpanParser will parse all those values to a TimeSpan. e.g. TimeSpanParser.Parse("50 milliseconds")
Note: TimeSpanParser only does English, and it will not do the relative dates mentioned by others such as "3 months from today" (though it will handle the unambiguous "0 months"). I've considered adding relative dates but I don't personally have a need for them.
I'd still love if Humanizer added this functionality. I have a lot of unit tests you guys could use. They were more comprehensive than Microsoft's and I even found a bug in Microsoft's TimeSpan.Parse code that I got patched.