forked from noctivityinc/tickle
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
789855c
commit 02ccfaf
Showing
13 changed files
with
634 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
every 2 weeks => word 'week' found plus a number so the interval = number * 7 and start_date = today | ||
every second tuesday => => day of week found WITH number (ordinal converted to 2). interval = 30 with start_date = Chronic.parse(Ordinal Number Day Of Week 'in' Start Date Month) | ||
every sunday => day of week found without number. interval = 7, start_date = next day of week occurrence | ||
every other day => word 'day' found with word 'other.' interval = 2, start_date = today | ||
every fourth thursday => day of week found WITH number (ordinal converted to 4). interval = 30 with start_date = next occurrence of 'event' as parsed by chronic | ||
on the 15th of each month => 'each month' becomes interval = 30, number found + start month through chronic equals start date | ||
on the 15th of November => month found with number. interval = 365, start_date = Chronic.parse(month + number) | ||
on the second monday in April => month, day and number found. interval = 365, start_date = Chronic.parse(ordinal number form of number, day of week, month) | ||
every November 15th => month found with number. interval = 365, start_date = Chronic.parse(month + number) | ||
every day => word 'day' found without a number. interval = 1. start_day = today | ||
every week => word 'week' found without a number. interval = 7. start_day = today | ||
every month => word 'month' found without a number. interval = 30. start_day = today |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
module Tickle | ||
class << self | ||
|
||
def guess() | ||
interval = guess_unit_types | ||
interval ||= guess_weekday | ||
interval ||= guess_weekday | ||
interval ||= guess_month_names | ||
interval ||= guess_number_and_unit | ||
interval ||= guess_special | ||
|
||
# defines the next occurrence of this tickle if not set in a guess routine | ||
@next ||= @start + (interval * 60 * 60 * 24) if interval | ||
return [@start.to_time, @next.to_time, interval] if interval | ||
end | ||
|
||
def guess_unit_types | ||
interval = 1 if token_types.same?([:day]) | ||
interval = 7 if token_types.same?([:week]) | ||
interval = 30 if token_types.same?([:month]) | ||
interval = 365 if token_types.same?([:year]) | ||
interval | ||
end | ||
|
||
def guess_weekday | ||
if token_types.same?([:weekday]) then | ||
@start = Chronic.parse(token_of_type(:weekday).start.to_s) | ||
interval = 7 | ||
end | ||
interval | ||
end | ||
|
||
def guess_month_names | ||
if token_types.same?([:month_name]) then | ||
@start = Chronic.parse("#{token_of_type(:month_name).start.to_s} 1") | ||
interval = 30 | ||
end | ||
interval | ||
end | ||
|
||
def guess_number_and_unit | ||
interval = token_of_type(:number).interval if token_types.same?([:number, :day]) | ||
interval = (token_of_type(:number).interval * 7) if token_types.same?([:number, :week]) | ||
interval = (token_of_type(:number).interval * 30) if token_types.same?([:number, :month]) | ||
interval = (token_of_type(:number).interval * 365) if token_types.same?([:number, :year]) | ||
interval | ||
end | ||
|
||
def guess_special | ||
interval = guess_special_other | ||
interval ||= guess_special_beginning | ||
interval ||= guess_special_middle | ||
interval ||= guess_special_end | ||
end | ||
|
||
private | ||
|
||
def guess_special_other | ||
interval = 2 if token_types.same?([:special, :day]) && token_of_type(:special).start == :other | ||
interval = 14 if token_types.same?([:special, :week]) && token_of_type(:special).start == :other | ||
if token_types.same?([:special, :month]) && token_of_type(:special).start == :other then interval = 60; @next = Chronic.parse('2 months from now'); end | ||
if token_types.same?([:special, :year]) && token_of_type(:special).start == :other then interval = 730; @next = Chronic.parse('2 years from now'); end | ||
interval | ||
end | ||
|
||
def guess_special_beginning | ||
if token_types.same?([:special, :week]) && token_of_type(:special).start == :beginning then interval = 7; @start = Chronic.parse('Sunday'); end | ||
if token_types.same?([:special, :month]) && token_of_type(:special).start == :beginning then interval = 30; @start = Chronic.parse('1st day next month'); end | ||
if token_types.same?([:special, :year]) && token_of_type(:special).start == :beginning then interval = 365; @start = Chronic.parse('1st day next year'); end | ||
interval | ||
end | ||
|
||
def guess_special_end | ||
if token_types.same?([:special, :week]) && token_of_type(:special).start == :end then interval = 7; @start = Chronic.parse('Saturday'); end | ||
if token_types.same?([:special, :month]) && token_of_type(:special).start == :end then interval = 30; @start = Date.new(Date.today.year, Date.today.month, Date.today.days_in_month); end | ||
if token_types.same?([:special, :year]) && token_of_type(:special).start == :end then interval = 365; @start = Date.new(Date.today.year, 12, 31); end | ||
interval | ||
end | ||
|
||
def guess_special_middle | ||
if token_types.same?([:special, :week]) && token_of_type(:special).start == :middle then interval = 7; @start = Chronic.parse('Wednesday'); end | ||
if token_types.same?([:special, :month]) && token_of_type(:special).start == :middle then | ||
interval = 30; | ||
@start = (Date.today.day >= 15 ? Chronic.parse('15th day of next month') : Date.new(Date.today.year, Date.today.month, 15)) | ||
end | ||
if token_types.same?([:special, :year]) && token_of_type(:special).start == :middle then | ||
interval = 365; | ||
@start = (Date.today.day >= 15 && Date.today.month >= 6 ? Date.new(Date.today.year+1, 6, 15) : Date.new(Date.today.year, 6, 15)) | ||
end | ||
interval | ||
end | ||
|
||
def token_of_type(type) | ||
@tokens.detect {|token| token.type == type} | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
class Tickle::Repeater < Chronic::Tag #:nodoc: | ||
# | ||
def self.scan(tokens) | ||
# for each token | ||
tokens.each do |token| | ||
token = self.scan_for_numbers(token) | ||
token = self.scan_for_month_names(token) | ||
token = self.scan_for_day_names(token) | ||
token = self.scan_for_special_text(token) | ||
token = self.scan_for_units(token) | ||
end | ||
tokens | ||
end | ||
|
||
def self.scan_for_numbers(token) | ||
num = Float(token.word) rescue nil | ||
token.update(:number, nil, num.to_i) if num | ||
token | ||
end | ||
|
||
def self.scan_for_month_names(token) | ||
scanner = {/^jan\.?(uary)?$/ => :january, | ||
/^feb\.?(ruary)?$/ => :february, | ||
/^mar\.?(ch)?$/ => :march, | ||
/^apr\.?(il)?$/ => :april, | ||
/^may$/ => :may, | ||
/^jun\.?e?$/ => :june, | ||
/^jul\.?y?$/ => :july, | ||
/^aug\.?(ust)?$/ => :august, | ||
/^sep\.?(t\.?|tember)?$/ => :september, | ||
/^oct\.?(ober)?$/ => :october, | ||
/^nov\.?(ember)?$/ => :november, | ||
/^dec\.?(ember)?$/ => :december} | ||
scanner.keys.each do |scanner_item| | ||
token.update(:month_name, scanner[scanner_item], 30) if scanner_item =~ token.word | ||
end | ||
token | ||
end | ||
|
||
def self.scan_for_day_names(token) | ||
scanner = {/^m[ou]n(day)?$/ => :monday, | ||
/^t(ue|eu|oo|u|)s(day)?$/ => :tuesday, | ||
/^tue$/ => :tuesday, | ||
/^we(dnes|nds|nns)day$/ => :wednesday, | ||
/^wed$/ => :wednesday, | ||
/^th(urs|ers)day$/ => :thursday, | ||
/^thu$/ => :thursday, | ||
/^fr[iy](day)?$/ => :friday, | ||
/^sat(t?[ue]rday)?$/ => :saturday, | ||
/^su[nm](day)?$/ => :sunday} | ||
scanner.keys.each do |scanner_item| | ||
token.update(:weekday, scanner[scanner_item], 7) if scanner_item =~ token.word | ||
end | ||
token | ||
end | ||
|
||
def self.scan_for_special_text(token) | ||
scanner = {/^other$/ => :other, | ||
/^begin(ing|ning)?$/ => :beginning, | ||
/^start$/ => :beginning, | ||
/^end$/ => :end, | ||
/^mid(d)?le$/ => :middle} | ||
scanner.keys.each do |scanner_item| | ||
token.update(:special, scanner[scanner_item], 7) if scanner_item =~ token.word | ||
end | ||
token | ||
end | ||
|
||
def self.scan_for_units(token) | ||
scanner = {/^year(ly)?s?$/ => {:type => :year, :interval => 365, :start => :today}, | ||
/^month(ly)?s?$/ => {:type => :month, :interval => 30, :start => :today}, | ||
/^fortnights?$/ => {:type => :fortnight, :interval => 365, :start => :today}, | ||
/^week(ly)?s?$/ => {:type => :week, :interval => 7, :start => :today}, | ||
/^weekends?$/ => {:type => :weekend, :interval => 7, :start => :saturday}, | ||
/^days?$/ => {:type => :day, :interval => 1, :start => :today}, | ||
/^daily?$/ => {:type => :day, :interval => 1, :start => :today}} | ||
scanner.keys.each do |scanner_item| | ||
if scanner_item =~ token.word | ||
token.update(scanner[scanner_item][:type], scanner[scanner_item][:start], scanner[scanner_item][:interval]) if scanner_item =~ token.word | ||
end | ||
end | ||
token | ||
end | ||
|
||
end |
Oops, something went wrong.