3 * Contributed to the Apache Software Foundation by:
5 * fork me at https://github.com/mobz/date-range-parser
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
15 http://www.apache.org/licenses/LICENSE-2.0
17 Unless required by applicable law or agreed to in writing,
18 software distributed under the License is distributed on an
19 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 KIND, either express or implied. See the License for the
21 specific language governing permissions and limitations
28 var drp = window.dateRangeParser = {};
30 drp.defaultRange = 1000 * 60 * 60 * 24;
32 drp.now = null; // set a different value for now than the time at function invocation
34 drp.parse = function(v) {
36 var r = drp._parse(v);
37 r.end && r.end--; // remove 1 millisecond from the final end range
44 drp.print = function(t, p) {
45 var format = ["", "-", "-", " ", ":", ":", "."];
46 var da = makeArray(t);
48 for(var i = 0; i <= p; i++) {
49 str += format[i] + (da[i] < 10 ? "0" : "") + da[i];
58 "yr" : 365*24*60*60*1000,
59 "mon" : 31*24*60*60*1000,
60 "day" : 24*60*60*1000,
67 "yr" : "y,yr,yrs,year,years",
68 "mon" : "mo,mon,mos,mons,month,months",
69 "day" : "d,dy,dys,day,days",
70 "hr" : "h,hr,hrs,hour,hours",
71 "min" : "m,min,mins,minute,minutes",
72 "sec" : "s,sec,secs,second,seconds"
75 for(var key in alias_lu) {
76 if(alias_lu.hasOwnProperty(key)) {
77 var aliases = alias_lu[key].split(",");
78 for(var i = 0; i < aliases.length; i++) {
79 drp._relTokens[aliases[i]] = values[key];
85 function makeArray(d) {
87 return [ da.getUTCFullYear(), da.getUTCMonth()+1, da.getUTCDate(), da.getUTCHours(), da.getUTCMinutes(), da.getUTCSeconds(), da.getUTCMilliseconds() ];
90 function fromArray(a) {
91 var d = [].concat(a); d[1]--;
92 return Date.UTC.apply(null, d);
95 drp._parse = function parse(v) {
96 var now = this.now || new Date().getTime();
98 function precArray(d, p, offset) {
99 var tn = makeArray(d);
100 tn[p] += offset || 0;
101 for(var i = p+1; i < 7; i++) {
102 tn[i] = i < 3 ? 1 : 0;
106 function makePrecRange(dt, p, r) {
108 ret.start = fromArray(dt);
110 ret.end = fromArray(dt);
113 function procTerm(term) {
114 var m = term.replace(/\s/g, "").toLowerCase().match(/^([a-z ]+)$|^([ 0-9:-]+)$|^(\d+[a-z]+)$/);
115 if(m[1]) { // matches ([a-z ]+)
116 function dra(p, o, r) {
117 var dt = precArray(now, p, o);
119 dt[2] -= new Date(fromArray(dt)).getUTCDay();
121 return makePrecRange(dt, p, r);
124 case "now" : return { start: now, end: now, now: now };
125 case "today" : return dra( 2, 0 );
126 case "thisweek" : return dra( 2, 0, 7 );
127 case "thismonth" : return dra( 1, 0 );
128 case "thisyear" : return dra( 0, 0 );
129 case "yesterday" : return dra( 2, -1 );
130 case "lastweek" : return dra( 2, -7, 7 );
131 case "lastmonth" : return dra( 1, -1 );
132 case "lastyear" : return dra( 0, -1 );
133 case "tomorrow" : return dra( 2, 1 );
134 case "nextweek" : return dra( 2, 7, 7 );
135 case "nextmonth" : return dra( 1, 1 );
136 case "nextyear" : return dra(0, 1 );
138 throw "unknown token " + m[1];
139 } else if(m[2]) { // matches ([ 0-9:-]+)
141 var dt = m[2].match(/^(?:(\d{4})(?:\-(\d\d))?(?:\-(\d\d))?)? ?(?:(\d{1,2})(?:\:(\d\d)(?:\:(\d\d))?)?)?$/);
143 for(var p = 0, z = false, i = 0; i < 7; i++) {
145 dn[i] = parseInt(dt[i], 10);
150 dn[i] = i < 3 ? 1 : 0;
153 return makePrecRange(dn, p);
154 } else if(m[3]) { // matches (\d+[a-z]{1,4})
155 var dr = m[3].match(/(\d+)\s*([a-z]+)/i);
156 var n = parseInt(dr[1], 10);
157 return { rel: n * drp._relTokens[dr[2]] };
159 throw "unknown term " + term;
163 return { start: null, end: null };
165 var terms = v.split(/\s*([^<>]*[^<>-])?\s*(->|<>|<)?\s*([^<>]+)?\s*/);
167 var term1 = terms[1] ? procTerm(terms[1]) : null;
168 var op = terms[2] || "";
169 var term2 = terms[3] ? procTerm(terms[3]) : null;
171 if(op === "<" || op === "->" ) {
172 if(term1 && !term2) {
173 return { start: term1.start, end: null };
174 } else if(!term1 && term2) {
175 return { start: null, end: term2.end };
178 return { start: term1.start, end: term1.end + term2.rel };
179 } else if(term1.rel) {
180 return { start: term2.start - term1.rel, end: term2.end };
182 return { start: term1.start, end: term2.end };
185 } else if(op === "<>") {
187 return { start: term1.start - drp.defaultRange, end: term1.end + drp.defaultRange }
189 if(! ("rel" in term2)) throw "second term did not hav a range";
190 return { start: term1.start - term2.rel, end: term1.end + term2.rel };
194 return { start: now - term1.rel, end: now + term1.rel };
195 } else if(term1.now) {
196 return { start: term1.now - drp.defaultRange, end: term1.now + drp.defaultRange };
198 return { start: term1.start, end: term1.end };
201 throw "could not process value " + v;