2150 |
mathias |
1 |
if(!dojo._hasResource["dojo.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojo.date"] = true;
|
|
|
3 |
dojo.provide("dojo.date");
|
|
|
4 |
|
|
|
5 |
dojo.date.getDaysInMonth = function(/*Date*/dateObject){
|
|
|
6 |
// summary:
|
|
|
7 |
// Returns the number of days in the month used by dateObject
|
|
|
8 |
var month = dateObject.getMonth();
|
|
|
9 |
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
|
10 |
if(month == 1 && dojo.date.isLeapYear(dateObject)){ return 29; } // Number
|
|
|
11 |
return days[month]; // Number
|
|
|
12 |
}
|
|
|
13 |
|
|
|
14 |
dojo.date.isLeapYear = function(/*Date*/dateObject){
|
|
|
15 |
// summary:
|
|
|
16 |
// Determines if the year of the dateObject is a leap year
|
|
|
17 |
// description:
|
|
|
18 |
// Leap years are years with an additional day YYYY-02-29, where the
|
|
|
19 |
// year number is a multiple of four with the following exception: If
|
|
|
20 |
// a year is a multiple of 100, then it is only a leap year if it is
|
|
|
21 |
// also a multiple of 400. For example, 1900 was not a leap year, but
|
|
|
22 |
// 2000 is one.
|
|
|
23 |
|
|
|
24 |
var year = dateObject.getFullYear();
|
|
|
25 |
return !(year%400) || (!(year%4) && !!(year%100)); // Boolean
|
|
|
26 |
}
|
|
|
27 |
|
|
|
28 |
// FIXME: This is not localized
|
|
|
29 |
dojo.date.getTimezoneName = function(/*Date*/dateObject){
|
|
|
30 |
// summary:
|
|
|
31 |
// Get the user's time zone as provided by the browser
|
|
|
32 |
// dateObject:
|
|
|
33 |
// Needed because the timezone may vary with time (daylight savings)
|
|
|
34 |
// description:
|
|
|
35 |
// Try to get time zone info from toString or toLocaleString method of
|
|
|
36 |
// the Date object -- UTC offset is not a time zone. See
|
|
|
37 |
// http://www.twinsun.com/tz/tz-link.htm Note: results may be
|
|
|
38 |
// inconsistent across browsers.
|
|
|
39 |
|
|
|
40 |
var str = dateObject.toString(); // Start looking in toString
|
|
|
41 |
var tz = ''; // The result -- return empty string if nothing found
|
|
|
42 |
var match;
|
|
|
43 |
|
|
|
44 |
// First look for something in parentheses -- fast lookup, no regex
|
|
|
45 |
var pos = str.indexOf('(');
|
|
|
46 |
if(pos > -1){
|
|
|
47 |
tz = str.substring(++pos, str.indexOf(')'));
|
|
|
48 |
}else{
|
|
|
49 |
// If at first you don't succeed ...
|
|
|
50 |
// If IE knows about the TZ, it appears before the year
|
|
|
51 |
// Capital letters or slash before a 4-digit year
|
|
|
52 |
// at the end of string
|
|
|
53 |
var pat = /([A-Z\/]+) \d{4}$/;
|
|
|
54 |
if((match = str.match(pat))){
|
|
|
55 |
tz = match[1];
|
|
|
56 |
}else{
|
|
|
57 |
// Some browsers (e.g. Safari) glue the TZ on the end
|
|
|
58 |
// of toLocaleString instead of putting it in toString
|
|
|
59 |
str = dateObject.toLocaleString();
|
|
|
60 |
// Capital letters or slash -- end of string,
|
|
|
61 |
// after space
|
|
|
62 |
pat = / ([A-Z\/]+)$/;
|
|
|
63 |
if((match = str.match(pat))){
|
|
|
64 |
tz = match[1];
|
|
|
65 |
}
|
|
|
66 |
}
|
|
|
67 |
}
|
|
|
68 |
|
|
|
69 |
// Make sure it doesn't somehow end up return AM or PM
|
|
|
70 |
return (tz == 'AM' || tz == 'PM') ? '' : tz; // String
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
// Utility methods to do arithmetic calculations with Dates
|
|
|
74 |
|
|
|
75 |
dojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
|
|
|
76 |
// summary:
|
|
|
77 |
// Compare two date objects by date, time, or both.
|
|
|
78 |
// description:
|
|
|
79 |
// Returns 0 if equal, positive if a > b, else negative.
|
|
|
80 |
// date1:
|
|
|
81 |
// Date object
|
|
|
82 |
// date2:
|
|
|
83 |
// Date object. If not specified, the current Date is used.
|
|
|
84 |
// portion:
|
|
|
85 |
// A string indicating the "date" or "time" portion of a Date object.
|
|
|
86 |
// Compares both "date" and "time" by default. One of the following:
|
|
|
87 |
// "date", "time", "datetime"
|
|
|
88 |
|
|
|
89 |
// Extra step required in copy for IE - see #3112
|
|
|
90 |
date1 = new Date(Number(date1));
|
|
|
91 |
date2 = new Date(Number(date2 || new Date()));
|
|
|
92 |
|
|
|
93 |
if(typeof portion !== "undefined"){
|
|
|
94 |
if(portion == "date"){
|
|
|
95 |
// Ignore times and compare dates.
|
|
|
96 |
date1.setHours(0, 0, 0, 0);
|
|
|
97 |
date2.setHours(0, 0, 0, 0);
|
|
|
98 |
}else if(portion == "time"){
|
|
|
99 |
// Ignore dates and compare times.
|
|
|
100 |
date1.setFullYear(0, 0, 0);
|
|
|
101 |
date2.setFullYear(0, 0, 0);
|
|
|
102 |
}
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
if(date1 > date2){ return 1; } // int
|
|
|
106 |
if(date1 < date2){ return -1; } // int
|
|
|
107 |
return 0; // int
|
|
|
108 |
};
|
|
|
109 |
|
|
|
110 |
dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
|
|
|
111 |
// summary:
|
|
|
112 |
// Add to a Date in intervals of different size, from milliseconds to years
|
|
|
113 |
// date: Date
|
|
|
114 |
// Date object to start with
|
|
|
115 |
// interval:
|
|
|
116 |
// A string representing the interval. One of the following:
|
|
|
117 |
// "year", "month", "day", "hour", "minute", "second",
|
|
|
118 |
// "millisecond", "quarter", "week", "weekday"
|
|
|
119 |
// amount:
|
|
|
120 |
// How much to add to the date.
|
|
|
121 |
|
|
|
122 |
var sum = new Date(Number(date)); // convert to Number before copying to accomodate IE (#3112)
|
|
|
123 |
var fixOvershoot = false;
|
|
|
124 |
var property = "Date";
|
|
|
125 |
|
|
|
126 |
switch(interval){
|
|
|
127 |
case "day":
|
|
|
128 |
break;
|
|
|
129 |
case "weekday":
|
|
|
130 |
//i18n FIXME: assumes Saturday/Sunday weekend, but even this is not standard. There are CLDR entries to localize this.
|
|
|
131 |
var days, weeks;
|
|
|
132 |
var adj = 0;
|
|
|
133 |
// Divide the increment time span into weekspans plus leftover days
|
|
|
134 |
// e.g., 8 days is one 5-day weekspan / and two leftover days
|
|
|
135 |
// Can't have zero leftover days, so numbers divisible by 5 get
|
|
|
136 |
// a days value of 5, and the remaining days make up the number of weeks
|
|
|
137 |
var mod = amount % 5;
|
|
|
138 |
if(!mod){
|
|
|
139 |
days = (amount > 0) ? 5 : -5;
|
|
|
140 |
weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
|
|
|
141 |
}else{
|
|
|
142 |
days = mod;
|
|
|
143 |
weeks = parseInt(amount/5);
|
|
|
144 |
}
|
|
|
145 |
// Get weekday value for orig date param
|
|
|
146 |
var strt = date.getDay();
|
|
|
147 |
// Orig date is Sat / positive incrementer
|
|
|
148 |
// Jump over Sun
|
|
|
149 |
if(strt == 6 && amount > 0){
|
|
|
150 |
adj = 1;
|
|
|
151 |
}else if(strt == 0 && amount < 0){
|
|
|
152 |
// Orig date is Sun / negative incrementer
|
|
|
153 |
// Jump back over Sat
|
|
|
154 |
adj = -1;
|
|
|
155 |
}
|
|
|
156 |
// Get weekday val for the new date
|
|
|
157 |
var trgt = strt + days;
|
|
|
158 |
// New date is on Sat or Sun
|
|
|
159 |
if(trgt == 0 || trgt == 6){
|
|
|
160 |
adj = (amount > 0) ? 2 : -2;
|
|
|
161 |
}
|
|
|
162 |
// Increment by number of weeks plus leftover days plus
|
|
|
163 |
// weekend adjustments
|
|
|
164 |
amount = 7 * weeks + days + adj;
|
|
|
165 |
break;
|
|
|
166 |
case "year":
|
|
|
167 |
property = "FullYear";
|
|
|
168 |
// Keep increment/decrement from 2/29 out of March
|
|
|
169 |
fixOvershoot = true;
|
|
|
170 |
break;
|
|
|
171 |
case "week":
|
|
|
172 |
amount *= 7;
|
|
|
173 |
break;
|
|
|
174 |
case "quarter":
|
|
|
175 |
// Naive quarter is just three months
|
|
|
176 |
amount *= 3;
|
|
|
177 |
// fallthrough...
|
|
|
178 |
case "month":
|
|
|
179 |
// Reset to last day of month if you overshoot
|
|
|
180 |
fixOvershoot = true;
|
|
|
181 |
property = "Month";
|
|
|
182 |
break;
|
|
|
183 |
case "hour":
|
|
|
184 |
case "minute":
|
|
|
185 |
case "second":
|
|
|
186 |
case "millisecond":
|
|
|
187 |
property = "UTC" + interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
|
|
|
188 |
}
|
|
|
189 |
|
|
|
190 |
if(property){
|
|
|
191 |
sum["set"+property](sum["get"+property]()+amount);
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
if(fixOvershoot && (sum.getDate() < date.getDate())){
|
|
|
195 |
sum.setDate(0);
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
return sum; // Date
|
|
|
199 |
};
|
|
|
200 |
|
|
|
201 |
dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
|
|
|
202 |
// summary:
|
|
|
203 |
// Get the difference in a specific unit of time (e.g., number of
|
|
|
204 |
// months, weeks, days, etc.) between two dates, rounded to the
|
|
|
205 |
// nearest integer.
|
|
|
206 |
// date1:
|
|
|
207 |
// Date object
|
|
|
208 |
// date2:
|
|
|
209 |
// Date object. If not specified, the current Date is used.
|
|
|
210 |
// interval:
|
|
|
211 |
// A string representing the interval. One of the following:
|
|
|
212 |
// "year", "month", "day", "hour", "minute", "second",
|
|
|
213 |
// "millisecond", "quarter", "week", "weekday"
|
|
|
214 |
// Defaults to "day".
|
|
|
215 |
|
|
|
216 |
date2 = date2 || new Date();
|
|
|
217 |
interval = interval || "day";
|
|
|
218 |
var yearDiff = date2.getFullYear() - date1.getFullYear();
|
|
|
219 |
var delta = 1; // Integer return value
|
|
|
220 |
|
|
|
221 |
switch(interval){
|
|
|
222 |
case "quarter":
|
|
|
223 |
var m1 = date1.getMonth();
|
|
|
224 |
var m2 = date2.getMonth();
|
|
|
225 |
// Figure out which quarter the months are in
|
|
|
226 |
var q1 = Math.floor(m1/3) + 1;
|
|
|
227 |
var q2 = Math.floor(m2/3) + 1;
|
|
|
228 |
// Add quarters for any year difference between the dates
|
|
|
229 |
q2 += (yearDiff * 4);
|
|
|
230 |
delta = q2 - q1;
|
|
|
231 |
break;
|
|
|
232 |
case "weekday":
|
|
|
233 |
var days = Math.round(dojo.date.difference(date1, date2, "day"));
|
|
|
234 |
var weeks = parseInt(dojo.date.difference(date1, date2, "week"));
|
|
|
235 |
var mod = days % 7;
|
|
|
236 |
|
|
|
237 |
// Even number of weeks
|
|
|
238 |
if(mod == 0){
|
|
|
239 |
days = weeks*5;
|
|
|
240 |
}else{
|
|
|
241 |
// Weeks plus spare change (< 7 days)
|
|
|
242 |
var adj = 0;
|
|
|
243 |
var aDay = date1.getDay();
|
|
|
244 |
var bDay = date2.getDay();
|
|
|
245 |
|
|
|
246 |
weeks = parseInt(days/7);
|
|
|
247 |
mod = days % 7;
|
|
|
248 |
// Mark the date advanced by the number of
|
|
|
249 |
// round weeks (may be zero)
|
|
|
250 |
var dtMark = new Date(date1);
|
|
|
251 |
dtMark.setDate(dtMark.getDate()+(weeks*7));
|
|
|
252 |
var dayMark = dtMark.getDay();
|
|
|
253 |
|
|
|
254 |
// Spare change days -- 6 or less
|
|
|
255 |
if(days > 0){
|
|
|
256 |
switch(true){
|
|
|
257 |
// Range starts on Sat
|
|
|
258 |
case aDay == 6:
|
|
|
259 |
adj = -1;
|
|
|
260 |
break;
|
|
|
261 |
// Range starts on Sun
|
|
|
262 |
case aDay == 0:
|
|
|
263 |
adj = 0;
|
|
|
264 |
break;
|
|
|
265 |
// Range ends on Sat
|
|
|
266 |
case bDay == 6:
|
|
|
267 |
adj = -1;
|
|
|
268 |
break;
|
|
|
269 |
// Range ends on Sun
|
|
|
270 |
case bDay == 0:
|
|
|
271 |
adj = -2;
|
|
|
272 |
break;
|
|
|
273 |
// Range contains weekend
|
|
|
274 |
case (dayMark + mod) > 5:
|
|
|
275 |
adj = -2;
|
|
|
276 |
}
|
|
|
277 |
}else if(days < 0){
|
|
|
278 |
switch(true){
|
|
|
279 |
// Range starts on Sat
|
|
|
280 |
case aDay == 6:
|
|
|
281 |
adj = 0;
|
|
|
282 |
break;
|
|
|
283 |
// Range starts on Sun
|
|
|
284 |
case aDay == 0:
|
|
|
285 |
adj = 1;
|
|
|
286 |
break;
|
|
|
287 |
// Range ends on Sat
|
|
|
288 |
case bDay == 6:
|
|
|
289 |
adj = 2;
|
|
|
290 |
break;
|
|
|
291 |
// Range ends on Sun
|
|
|
292 |
case bDay == 0:
|
|
|
293 |
adj = 1;
|
|
|
294 |
break;
|
|
|
295 |
// Range contains weekend
|
|
|
296 |
case (dayMark + mod) < 0:
|
|
|
297 |
adj = 2;
|
|
|
298 |
}
|
|
|
299 |
}
|
|
|
300 |
days += adj;
|
|
|
301 |
days -= (weeks*2);
|
|
|
302 |
}
|
|
|
303 |
delta = days;
|
|
|
304 |
break;
|
|
|
305 |
case "year":
|
|
|
306 |
delta = yearDiff;
|
|
|
307 |
break;
|
|
|
308 |
case "month":
|
|
|
309 |
delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
|
|
|
310 |
break;
|
|
|
311 |
case "week":
|
|
|
312 |
// Truncate instead of rounding
|
|
|
313 |
// Don't use Math.floor -- value may be negative
|
|
|
314 |
delta = parseInt(dojo.date.difference(date1, date2, "day")/7);
|
|
|
315 |
break;
|
|
|
316 |
case "day":
|
|
|
317 |
delta /= 24;
|
|
|
318 |
// fallthrough
|
|
|
319 |
case "hour":
|
|
|
320 |
delta /= 60;
|
|
|
321 |
// fallthrough
|
|
|
322 |
case "minute":
|
|
|
323 |
delta /= 60;
|
|
|
324 |
// fallthrough
|
|
|
325 |
case "second":
|
|
|
326 |
delta /= 1000;
|
|
|
327 |
// fallthrough
|
|
|
328 |
case "millisecond":
|
|
|
329 |
delta *= date2.getTime() - date1.getTime();
|
|
|
330 |
}
|
|
|
331 |
|
|
|
332 |
// Round for fractional values and DST leaps
|
|
|
333 |
return Math.round(delta); // Number (integer)
|
|
|
334 |
};
|
|
|
335 |
|
|
|
336 |
}
|