ndp.lua

Sun, 21 Jun 2009 17:42:50 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Sun, 21 Jun 2009 17:42:50 +0100
changeset 0
44416491923e
child 1
29a492373a7c
permissions
-rw-r--r--

Initial commit of ndp, the natural date processing library

0
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 module(..., package.seeall);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 require "luarocks.require"
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 require "lpeg"
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 -- Add case-insensitive string matching to Lpeg
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 function lpeg.Pi(s)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 local patt = lpeg.P(true);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 for c in s:gmatch(".") do
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 patt = patt * (lpeg.P(c:lower()) + lpeg.P(c:upper()));
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 return patt;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 function lpeg.one_of(list)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 local patt = lpeg.P(false);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 for _, match in ipairs(list) do
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 patt = patt + lpeg.Pi(match);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 return patt;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 local ordinal = lpeg.P{ lpeg.C(lpeg.R("09")^-2) * (lpeg.Pi("st") + lpeg.Pi("nd") + lpeg.Pi("rd") + lpeg.Pi("th")) + 1 * lpeg.V(1) };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 local number = lpeg.R "09"^1
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 local day_name = lpeg.one_of {'monday', 'tuesday', 'wednesday',
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 'thursday', 'friday', 'saturday', 'sunday'}
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 local month_name = lpeg.one_of {'january', 'february', 'march', 'april', 'may', 'june',
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 'july', 'august', 'september', 'october', 'november', 'december' }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 local year = (lpeg.R("09")^4)^-4
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 local unit_of_time = lpeg.one_of { 'second', 'minute', 'hour', 'day', 'week', 'month', 'year' }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 local time_of_day = lpeg.one_of { 'morning', 'noon', 'afternoon', 'evening', 'night', 'midnight' }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 local time_of_days = { morning = 09, noon = 12, afternoon = 13, evening = 17, night = 21, midnight = 00 }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 local quantity;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 local quantities = {
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 ["a"] = 1;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 ["an"] = 1;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 ["a couple of"] = 2;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 ["a few"] = 3;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 ["several"] = 3;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 -- Create 'quantity' to match any of the quantities we know
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 do
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 local quantity_list = {};
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 for k in pairs(quantities) do
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 quantity_list[#quantity_list+1] = k;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 table.sort(quantity_list, function (a,b) return #a>#b; end);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 quantity = number + lpeg.one_of(quantity_list);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 seconds_in_a = { second = 1 }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 seconds_in_a.minute = seconds_in_a.second * 60;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62 seconds_in_a.hour = seconds_in_a.minute * 60;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 seconds_in_a.day = seconds_in_a.hour * 24;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 seconds_in_a.week = seconds_in_a.day * 7;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 seconds_in_a.month = seconds_in_a.week * 4;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 seconds_in_a.year = seconds_in_a.day * 365;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 local function get_time_part(time, part)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 return os.date("*t", time)[part];
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 local function adjust_time(time, part, value)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 local split_time = os.date("*t", time);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 split_time[part] = value;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77 return os.time(split_time);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 function when(str, relative_to)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 local time = relative_to or os.time();
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 local P = lpeg.P;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 local patterns =
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 {
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 { P"tomorrow" /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 function ()
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 time = time + seconds_in_a.day;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 { P"next week" /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 function ()
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 time = time + seconds_in_a.week;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 { P"next year" /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 function ()
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96 time = adjust_time(time, "year", get_time_part(time, "year") + 1);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 { P"on "^0 * day_name /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99 function (day_name)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100 time = find_nearest_day_by_name(time, day_name);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 { P"in "^0 * month_name /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 function (month_name)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 time = find_nearest_month_by_name(time, month_name);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 { P"in "^0 * ( quantity * P" " * unit_of_time ) * (P"s"^-1) /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 function (number_and_unit)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 local number, unit = number_and_unit:gsub("^in ", ""):match("^(.+)%s+(.-)s?$");
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 number = quantities[number] or tonumber(number);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 time = time + seconds_in_a[unit] * number;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 { (P"this " + P"in the " + P"at ")^0 * time_of_day /
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 function (time_of_day)
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 time_of_day = time_of_day:match("%S+$");
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 time = adjust_time(time, "hour", time_of_days[time_of_day]);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118 if time_of_day == "noon" or time_of_day == "midnight" then
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 time = adjust_time(time, "min", 00);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120 else
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 time = adjust_time(time, "min", 30);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123 end };
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 }
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
126 local ret, pos;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
127 for _, pattern in pairs(patterns) do
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
128 ret = lpeg.match(lpeg.P{ pattern[1] + 1 * lpeg.V(1) }, str);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
129 if ret then
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
130 pos = ret;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
131 --print("Matches ".._.." until "..ret);
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
132 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
133 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
134
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
135 return time, pos;
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
136 end
44416491923e Initial commit of ndp, the natural date processing library
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
137

mercurial