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

Minutizer #231

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Minutizer #231

wants to merge 4 commits into from

Conversation

TalkativeTree
Copy link
Contributor

Add Chronic.minutize(text) to extract the duration from text.

I use this personally to extract the duration of events from updates or events to set the duration, start and end times, etc. I chose minutes, because most information displayed to users is in minutes or hours, but not seconds.

Some examples of use:

Chronic.minutize("2 hours, 30 min")
 => 150
Chronic.minutize("30 min")
 => 30
Chronic.minutize("The experiment lasted for 321 seconds") 
 =>  5.35
Chronic.minutize("I took one sleeping pill and slept for half a day") 
 => 720
Chronic.minutize("I was traveling for a week and a half")
 => 15120.0
Chronic.minutize("I traveled for 2 days, three hrs, and forty mintes")
 => 3100
Chronic.minutize("The conference lasted 2 weeks")
 =>  20160.0

Another cool thing you can do with this new feature is utilize Chronic's Span to return a span based on the text's create_at (or another anchoring time).

#Assume we have an Activity table with a created_at, duration, begin, and end.
# We want to figure out when it began and end, but all we have a text update/message about the activity

params[:message] = "I've been doing some example activity for 2 hours"
example_activity = Activity.create( message: params[:message])
example_activity.duration = Chronic.minutize( example_activity.message )
# => duration would equal the integer 120, representing 120 minutes

# Set the begin and end using just duration and created_at
example_activity.begin = example_activity.created_at
example_activity.end = example_activity.created_at - duration

# Another method using Chronic's Span class
start_time = example_activity.created_at
end_time   = example_activity.created_at - duration
time_span = Chronic::Span.new(start_time, end_time)

example_activity.begin = time_span.begin
example_activity.end = time_span.end

This is also useful to use during a model's callbacks, such as before_create or before_save.

…es from strings like 'It lasted 2 hours and 30 mintues'
…t as a string and return the duration found in that text as an integer/fixnum.

ex: Minutizer.new.minutize("It took me a 5 hours to write my tests") => 300
ex2: Minutizer.new.minituze("I spent 321 seconds contemplating this commit message") => 5.35
@TalkativeTree
Copy link
Contributor Author

I will also write up an explanation of minutize in the README and add it to the pull request if you want to add this.

@davispuh
Copy link
Collaborator

davispuh commented Dec 5, 2013

I'm not sure if Chronic is right gem for this kind of functionality. Chronic has always parsed only discrete times and not durations. Durations are parsed with chronic_duration gem

@davispuh
Copy link
Collaborator

davispuh commented Dec 5, 2013

Also I don't think it's good idea to use minutes, it doesn't matter what you've to display to user, but most people would expect to keep seconds internally and to show only minutes would just secs / 60

@TalkativeTree
Copy link
Contributor Author

Yeah, I was thinking about changing it to display seconds (would also require a name change). The one difference between this and ChronicDuration is CD is set to parse duration from specific strings like '4m20sec' where Minutizer parsers duration from text more similar to what Chronic would receive.

Something a little more Chronic might be to create a Chronic#parse_span method that incorporates what I've written for Minutizer.

@davispuh
Copy link
Collaborator

davispuh commented Dec 5, 2013

CD also parses natural texts, for example

ChronicDuration.parse('I drank 15 beers in 3 and a half hours')`
=> 12600.0

Most of these tests does pass for CD and I think it might be very useful to improve CD even more if you need some specific features (eg. Span for CD). Primarily because Chronic just isn't really meant for it and then when there will be need for more duration features we'll have to reimplement lot of stuff that's already in CD. Anyway it's up to @leejarvis

Another thing, I think that pre_normalize part (even in parser.rb) probably should be made in other gem like datetime_normalize or maybe numerizer could implement that functionality as it's quite often required and currently everyone just reimplements it themselves. Also I think that should remove numerizer code from Chronic and just use numerizer gem as CD already uses it.

@TalkativeTree
Copy link
Contributor Author

Regarding Chronic.parse_span, I was thinking it would be for sentences like:

'since last tuesday'
'until next tuesday'
'last night until this morning'
'yesterday until tomorrow'
'yesterday at 5pm until tomorrow at 8am'
'8am - 12pm'
'the last 3 days'
'the next 30 minutes'
'since August 30th'

which come from test code I've already written for span creation. parsing spans for these kind outside of Chronic would require recreating/copying a lot of what Chronic currently does.

@davispuh
Copy link
Collaborator

davispuh commented Dec 5, 2013

that would be useful functionality and would fit fine for Chronic, but I don't see how that's related to this Minutizer. When you parse such duration, it would return Span and with that can easily get length in seconds. Only currently Chronic doesn't really have any real support for such parsing, but for that feature 👍 if you implement.

@TalkativeTree
Copy link
Contributor Author

For most of the spans of time, like "yesterday until tomorrow," you don't need a duration. But for "next 3 hours" or "past 30 minutes" I believe you need some kind of duration or representation of that time difference from now.

Minutizer was built for the end goal of getting spans using Chronic, which is why I sent a pull request for it first. if @leejarvis gives parse_span the go ahead, I can build that feature for Chronic.

@davispuh
Copy link
Collaborator

davispuh commented Dec 5, 2013

It does make sense. And if "next 3 hours" returns span then yes it's fine for Chronic. Also Minutizer isn't really needed, because Chronic already have somewhat duration support internally, for example Chronic parses "after 3 hours" fine. So what I mean, Chronic shouldn't expose such functionality outside and use durations only internally which it already does (take a look at repeaters). Basically such span processing should happen same as typical parse - first we split input text in tokens, then we process each token and do rest stuff, etc. So we don't need Minutizer as we already have tokens ready for processing and that's why I'm saying Minutizer isn't good fit here but rather CD. Also Chronic support for durations is very poor as it's not DST aware (here's several issues opened about it) and should be reimplemented completely. For next week it uses week_start + WEEK_SECONDS and your Minutizer doesn't do any better. Besides seems digitize_time is kinda dublicate/same as those day/week/etc repeaters. It would be very useful to create new class ChronicDuration which would implement it all properly rather than your Minutizer.

@leejarvis
Copy link
Collaborator

I like this, but I agree that it could be a confusing thing to add to Chronic. I also agree something like this should always return seconds over minutes. I'm happy to have a parse_duration or parse_span method that does something like this, though.

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

Successfully merging this pull request may close these issues.

None yet

3 participants