1Date.prototype.stdTimezoneOffset = function () { 2 var fy = this.getFullYear(); 3 if (!Date.prototype.stdTimezoneOffset.cache.hasOwnProperty(fy)) { 4 5 var maxOffset = new Date(fy, 0, 1).getTimezoneOffset(); 6 var monthsTestOrder = [6, 7, 5, 8, 4, 9, 3, 10, 2, 11, 1]; 7 8 for (var mi = 0; mi < 12; mi++) { 9 var offset = new Date(fy, monthsTestOrder[mi], 1).getTimezoneOffset(); 10 if (offset != maxOffset) { 11 maxOffset = Math.max(maxOffset, offset); 12 break; 13 } 14 } 15 Date.prototype.stdTimezoneOffset.cache[fy] = maxOffset; 16 } 17 return Date.prototype.stdTimezoneOffset.cache[fy]; 18}; 19 20Date.prototype.stdTimezoneOffset.cache = {}; 21 22Date.prototype.isDST = function () { 23 return this.getTimezoneOffset() < this.stdTimezoneOffset(); 24}; 25(function () { 26 27 var AM = 'am' 28 , PM = 'pm' 29 , periodRegex = new RegExp('([ap](\\.?)(m\\.?)?)', 'i') 30 , timeRegex = new RegExp('^(10|11|12|0?[1-9])(?::|\\.)?([0-5][0-9])?' 31 + periodRegex.source + '?$', 'i') 32 , formatRegex = new RegExp('^(h|hh)([:|\.])?(mm)?( ?)' 33 + periodRegex.source + '?$', 'i'); 34 35 // play nice with both node.js and browser 36 if (typeof module !== 'undefined' && module.exports) module.exports = Time; 37 else window.Time = Time; 38 39 /* 40 * Time constructor works with(out) 'new' 41 * 42 * @time (optional) string or number representing a time. 43 * e.g. 7, 1234, '7', '7:00', '12.14' 44 * 45 * If not provided, current time is used. 46 */ 47 function Time(time) { 48 if (!(this instanceof Time)) return new Time(time); 49 50 var hours, minutes, period = null; 51 52 if (time) { 53 var result = timeRegex.exec(sanitize(time)); 54 if (result) { 55 hours = parseInt(result[1], 10); 56 minutes = result[2] ? parseInt(result[2], 10) : 0; 57 period = parsePeriod(result[3]); 58 } 59 } else { 60 // set to current time 61 var d = new Date(); 62 hours = d.getHours(); 63 period = hours > 11 ? PM : AM; 64 if (hours > 12) hours -= 12; 65 if (hours === 0) hours = 12; 66 minutes = d.getMinutes(); 67 } 68 69 // gets or sets hours 70 this.hours = function (newHours) { 71 if (!newHours) return hours; 72 hours = parseInt(newHours, 10); 73 }; 74 75 // gets or sets minutes 76 this.minutes = function (newMinutes) { 77 if (!newMinutes) return minutes; 78 minutes = parseInt(newMinutes, 10); 79 }; 80 81 // gets or sets period 82 this.period = function (newPeriod) { 83 if (!newPeriod) return period; 84 period = parsePeriod(newPeriod); 85 }; 86 } 87 88 /* 89 * Find the next immediate corresponding Date. 90 * 91 * Assume it's 3:15 pm Aug 10: 92 * Time('3:15').nextDate() // 3:15 pm Aug 10 93 * Time('415').nextDate() // 4:15 pm Aug 10 94 * Time('2').nextDate() // 2:00 am Aug 11 95 */ 96 Time.prototype.nextDate = function () { 97 if (!this.isValid()) return null; 98 99 var hours = this.hours() === 12 ? 0 : this.hours(); // uniformly handle am/pm adjustments 100 if (this.period() === PM) hours += 12; 101 var d = new Date(); 102 d.setHours(hours); 103 d.setMinutes(this.minutes()); 104 d.setSeconds(0); 105 d.setMilliseconds(0); 106 107 // if it has already passed, add 12 hours at a time until it's in the future 108 while (new Date() > d) d.setHours(d.getHours() + 12); 109 110 // make sure we're in the correct period 111 if (d.getHours() > 11 && this.period() === AM) d.setHours(d.getHours() + 12) 112 else if (d.getHours() < 12 && this.period() === PM) d.setHours(d.getHours() + 12) 113 114 return d; 115 }; 116 117 Time.isValid = function (time) { 118 return timeRegex.test(sanitize(time)); 119 }; 120 121 Time.prototype.isValid = function () { 122 return Time.isValid(toString(this)); 123 }; 124 125 /* 126 * This can be safely changed if so desired. 127 */ 128 Time.DEFAULT_TIME_FORMAT = 'h:mm am'; 129 130 /* 131 * Formats the time to the given format, or h:mm if one is not provided. 132 * 133 * If periods are specified in the format, they are only printed if known. 134 *
135 * If the time isn't valid, return 'invalid time'. 136 * If the format isn't valid, return 'invalid format'. 137 * 138 * This isn't every combination, but hopefully you get the gist of things. 139 * h:mm 12:00 (default) 140 * hh:mm 01:00 141 * h 1 142 * h 1:55 (input specified minutes, so we show them) 143 * h. 1.55 (if minutes are shown, use . for separator) 144 * hpm 1am 145 * h:mm a 1:55 p 146 * h:mm a 1:55 (input didn't specify period) 147 * h.mm am 1.55 pm 148 * h.mm A 1.55 P 149 * hh:mm a.m. 01:55 a.m. 150 * h:mma 1:55a 151 * h.mm 1.55 152 */ 153 Time.prototype.format = function (format) { 154 format = format || Time.DEFAULT_TIME_FORMAT; 155 if (!this.isValid()) { 156 return 'invalid time'; 157 } else if (!formatRegex.test(format)) { 158 return 'invalid format'; 159 } 160 return toString(this, format); 161 }; 162 163 /* 164 * Alias for `format`. 165 */ 166 Time.prototype.toString = Time.prototype.format; 167 168 /* 169 * (private) Format Time in the given format. 170 * 171 * @time Time instance 172 * @retun hh:mm e.g. 3:00, 12:23, undefined:undefined 173 */ 174 function toString(time, format) { 175 format = format || Time.DEFAULT_TIME_FORMAT; 176 var bits = formatRegex.exec(format); 177 var fHour = bits[1]; 178 var fMiddlebit = bits[2]; 179 var fMinutes = bits[3]; 180 var fPeriodSpace = bits[4]; 181 var fPeriod = bits[5]; 182 var fFirstPeriod = bits[6]; 183 var fPeriodM = bits[7]; 184 185 // always show hour 186 var hours = fHour.length == 2 ? padTime(time.hours()) : time.hours(); 187 188 // show if in the format or if non-zero and middlebit is provided 189 var minutes = (fMinutes || (fMiddlebit && time.minutes() !== 0)) ? 190 padTime(time.minutes()) : ''; 191 192 // show middlebit if we have minutes 193 var middlebit = (minutes && fMiddlebit) ? fMiddlebit : ''; 194 195 // show period if available and requested 196 var period = ''; 197 if (fPeriod && time.period()) { 198 var firstPeriod = time.period().charAt(0); 199 if (fPeriod.charAt(0) === fPeriod.charAt(0).toUpperCase()) { 200 firstPeriod = firstPeriod.toUpperCase(); 201 } 202 period = firstPeriod + fPeriod.slice(1); 203 } 204 205 // only show space if it was requested by format and there's a period 206 var space = (period && fPeriodSpace) ? fPeriodSpace : ''; 207 208 return '' + hours + middlebit + minutes + space + period; 209 } 210 211 function padTime(time) { 212 return time < 10 ? '0' + time : time; 213 } 214 215 /* 216 * (private) Force @time to a string and remove all whitespace. 217 * 218 * @time input 219 * @retun input as a string, with all white space removed 220 */ 221 function sanitize(time) { 222 return time.toString().replace(/\s/g, ''); 223 } 224 225 /* 226 * (private) 227 */ 228 function parsePeriod(period) { 229 if (!period || !period.match(periodRegex)) return null; 230 else if (period.match(/^p/i) != null) return PM; 231 return (period.match(/^a/i) != null) ? AM : null; 232 } 233})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.