Class: TellMeWhenever

Inherits:
Object
  • Object
show all
Defined in:
lib/tell_me_whenever.rb

Class Method Summary collapse

Class Method Details

.parse(str) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/tell_me_whenever.rb', line 8

def self.parse(str)
  str = str.downcase
  target = nil

  # figure out whether an exact date was used
  # match against months
  months = { "january" => 1,
    "february" => 2,
    "march" => 3,
    "april" => 4,
    "may" => 5,
    "june" => 6,
    "july" => 7,
    "august" => 8,
    "september" => 9,
    "october" => 10,
    "november" => 11,
    "december" => 12}

  targetMonth = 0
  months.each do |key, value|
    if str.include? key then
      targetMonth = value
    end
  end

  # match against weekdays
  weekdays = { "monday" => 1,
    "tuesday" => 2,
    "wednesday" => 3,
    "thursday" => 4,
    "friday" => 5,
    "saturday" => 6,
    "sunday" => 7}
  targetWeekday = 0
  weekdays.each do |key, value|
    if str.include? key then
      targetWeekday = value
    end
  end

  # match against date offset
  units = ["year", "month", "week", "day", "hour"]
  targetUnits = []
  units.each do |unit|
    if str.include? unit then
      targetUnits.push unit
    end
  end

  if targetMonth != 0 then
    target = DateTime.now.beginning_of_day.change({ month: targetMonth, day: 1, hour: 9 })

    # find out whether a specific day was specified
    str.scan(/\d+/).map(&:to_i).sort.reverse.each do |day|
      # is this date within this month?
      if target.end_of_month.day >= day
        target = target.change({day: day})
        break
      end
    end
  elsif targetWeekday != 0 then
    target = DateTime.now.beginning_of_day.change({ hour: 9 })

    # falls within this week or next week?
    if target.monday.next_day(targetWeekday - 1) < target then
      target = target.next_week.next_day(targetWeekday - 1).change({hour: 9})
    else
      target = target.monday.next_day(targetWeekday - 1).change({hour: 9})
    end
  elsif targetUnits.length > 0 then
    target = DateTime.now

    if(!targetUnits.include?("hour") && !targetUnits.include?("day")) then
      target = target.change({hour: 9})
    end

    # try to find all applicable quantifiers in the str string
    targetUnits.each do |unit|
      magnitude = 1
      first = str.slice(0, str.index(unit)).scan(/\d+/).map(&:to_i).reverse.first
      if first != nil then
        magnitude = first
      end

      # TODO flag special cases on magnitude limitations
      if unit == "year" then
        if magnitude > 100 then
          magnitude = 100
        end
        target = target + magnitude.years
      elsif unit == "month" then
        if magnitude > 1200 then
          magnitude = 1200
        end
        target = target + magnitude.months
      elsif unit == "week" then
        if magnitude > 63600 then
          magnitude = 63600
        end
        target = target + magnitude.weeks
      elsif unit == "day" then
        if magnitude > 100000 then
          magnitude = 100000
        end
        target = target + magnitude.days
      elsif unit == "hour" then
        if magnitude > 100000 then
          magnitude = 100000
        end
        target = target + magnitude.hours
      end
    end
  elsif str.include?("tomorrow") then
    target = DateTime.now.beginning_of_day.change({ hour: 9 }) + 1.days
  end

  return target
end