| Total Complexity | 78 |
| Complexity/F | 9.75 |
| Lines of Code | 277 |
| Function Count | 8 |
| Duplicated Lines | 277 |
| Ratio | 100 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like js/date.matt.kruse.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | // =================================================================== |
||
| 59 | View Code Duplication | var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); |
|
|
|
|||
| 60 | var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat'); |
||
| 61 | function LZ(x) {return(x<0||x>9?"":"0")+x} |
||
| 62 | |||
| 63 | // ------------------------------------------------------------------ |
||
| 64 | // isDate ( date_string, format_string ) |
||
| 65 | // Returns true if date string matches format of format string and |
||
| 66 | // is a valid date. Else returns false. |
||
| 67 | // It is recommended that you trim whitespace around the value before |
||
| 68 | // passing it to this function, as whitespace is NOT ignored! |
||
| 69 | // ------------------------------------------------------------------ |
||
| 70 | function isDate(val,format) { |
||
| 71 | var date=getDateFromFormat(val,format); |
||
| 72 | if (date==0) { return false; } |
||
| 73 | return true; |
||
| 74 | } |
||
| 75 | |||
| 76 | // ------------------------------------------------------------------- |
||
| 77 | // compareDates(date1,date1format,date2,date2format) |
||
| 78 | // Compare two date strings to see which is greater. |
||
| 79 | // Returns: |
||
| 80 | // 1 if date1 is greater than date2 |
||
| 81 | // 0 if date2 is greater than date1 of if they are the same |
||
| 82 | // -1 if either of the dates is in an invalid format |
||
| 83 | // ------------------------------------------------------------------- |
||
| 84 | function compareDates(date1,dateformat1,date2,dateformat2) { |
||
| 85 | var d1=getDateFromFormat(date1,dateformat1); |
||
| 86 | var d2=getDateFromFormat(date2,dateformat2); |
||
| 87 | if (d1==0 || d2==0) { |
||
| 88 | return -1; |
||
| 89 | } |
||
| 90 | else if (d1 > d2) { |
||
| 91 | return 1; |
||
| 92 | } |
||
| 93 | return 0; |
||
| 94 | } |
||
| 95 | |||
| 96 | // ------------------------------------------------------------------ |
||
| 97 | // formatDate (date_object, format) |
||
| 98 | // Returns a date in the output format specified. |
||
| 99 | // The format string uses the same abbreviations as in getDateFromFormat() |
||
| 100 | // ------------------------------------------------------------------ |
||
| 101 | function formatDate(date,format) { |
||
| 102 | format=format+""; |
||
| 103 | var result=""; |
||
| 104 | var i_format=0; |
||
| 105 | var c=""; |
||
| 106 | var token=""; |
||
| 107 | var y=date.getYear()+""; |
||
| 108 | var M=date.getMonth()+1; |
||
| 109 | var d=date.getDate(); |
||
| 110 | var E=date.getDay(); |
||
| 111 | var H=date.getHours(); |
||
| 112 | var m=date.getMinutes(); |
||
| 113 | var s=date.getSeconds(); |
||
| 114 | var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k; |
||
| 115 | // Convert real date parts into formatted versions |
||
| 116 | var value=new Object(); |
||
| 117 | if (y.length < 4) {y=""+(y-0+1900);} |
||
| 118 | value["y"]=""+y; |
||
| 119 | value["yyyy"]=y; |
||
| 120 | value["yy"]=y.substring(2,4); |
||
| 121 | value["M"]=M; |
||
| 122 | value["MM"]=LZ(M); |
||
| 123 | value["MMM"]=MONTH_NAMES[M-1]; |
||
| 124 | value["NNN"]=MONTH_NAMES[M+11]; |
||
| 125 | value["d"]=d; |
||
| 126 | value["dd"]=LZ(d); |
||
| 127 | value["E"]=DAY_NAMES[E+7]; |
||
| 128 | value["EE"]=DAY_NAMES[E]; |
||
| 129 | value["H"]=H; |
||
| 130 | value["HH"]=LZ(H); |
||
| 131 | if (H==0){value["h"]=12;} |
||
| 132 | else if (H>12){value["h"]=H-12;} |
||
| 133 | else {value["h"]=H;} |
||
| 134 | value["hh"]=LZ(value["h"]); |
||
| 135 | if (H>11){value["K"]=H-12;} else {value["K"]=H;} |
||
| 136 | value["k"]=H+1; |
||
| 137 | value["KK"]=LZ(value["K"]); |
||
| 138 | value["kk"]=LZ(value["k"]); |
||
| 139 | if (H > 11) { value["a"]="PM"; } |
||
| 140 | else { value["a"]="AM"; } |
||
| 141 | value["m"]=m; |
||
| 142 | value["mm"]=LZ(m); |
||
| 143 | value["s"]=s; |
||
| 144 | value["ss"]=LZ(s); |
||
| 145 | while (i_format < format.length) { |
||
| 146 | c=format.charAt(i_format); |
||
| 147 | token=""; |
||
| 148 | while ((format.charAt(i_format)==c) && (i_format < format.length)) { |
||
| 149 | token += format.charAt(i_format++); |
||
| 150 | } |
||
| 151 | if (value[token] != null) { result=result + value[token]; } |
||
| 152 | else { result=result + token; } |
||
| 153 | } |
||
| 154 | return result; |
||
| 155 | } |
||
| 156 | |||
| 157 | // ------------------------------------------------------------------ |
||
| 158 | // Utility functions for parsing in getDateFromFormat() |
||
| 159 | // ------------------------------------------------------------------ |
||
| 160 | function _isInteger(val) { |
||
| 161 | var digits="1234567890"; |
||
| 162 | for (var i=0; i < val.length; i++) { |
||
| 163 | if (digits.indexOf(val.charAt(i))==-1) { return false; } |
||
| 164 | } |
||
| 165 | return true; |
||
| 166 | } |
||
| 167 | function _getInt(str,i,minlength,maxlength) { |
||
| 168 | for (var x=maxlength; x>=minlength; x--) { |
||
| 169 | var token=str.substring(i,i+x); |
||
| 170 | if (token.length < minlength) { return null; } |
||
| 171 | if (_isInteger(token)) { return token; } |
||
| 172 | } |
||
| 173 | return null; |
||
| 174 | } |
||
| 175 | |||
| 176 | // ------------------------------------------------------------------ |
||
| 177 | // getDateFromFormat( date_string , format_string ) |
||
| 178 | // |
||
| 179 | // This function takes a date string and a format string. It matches |
||
| 180 | // If the date string matches the format string, it returns the |
||
| 181 | // getTime() of the date. If it does not match, it returns 0. |
||
| 182 | // ------------------------------------------------------------------ |
||
| 183 | function getDateFromFormat(val,format) { |
||
| 184 | val=val+""; |
||
| 185 | format=format+""; |
||
| 186 | var i_val=0; |
||
| 187 | var i_format=0; |
||
| 188 | var c=""; |
||
| 189 | var token=""; |
||
| 190 | var token2=""; |
||
| 191 | var x,y; |
||
| 192 | var now=new Date(); |
||
| 193 | var year=now.getYear(); |
||
| 194 | var month=now.getMonth()+1; |
||
| 195 | var date=1; |
||
| 196 | var hh=now.getHours(); |
||
| 197 | var mm=now.getMinutes(); |
||
| 198 | var ss=now.getSeconds(); |
||
| 199 | var ampm=""; |
||
| 200 | |||
| 201 | while (i_format < format.length) { |
||
| 202 | // Get next token from format string |
||
| 203 | c=format.charAt(i_format); |
||
| 204 | token=""; |
||
| 205 | while ((format.charAt(i_format)==c) && (i_format < format.length)) { |
||
| 206 | token += format.charAt(i_format++); |
||
| 207 | } |
||
| 208 | // Extract contents of value based on format token |
||
| 209 | if (token=="yyyy" || token=="yy" || token=="y") { |
||
| 210 | if (token=="yyyy") { x=4;y=4; } |
||
| 211 | if (token=="yy") { x=2;y=2; } |
||
| 212 | if (token=="y") { x=2;y=4; } |
||
| 213 | year=_getInt(val,i_val,x,y); |
||
| 214 | if (year==null) { return 0; } |
||
| 215 | i_val += year.length; |
||
| 216 | if (year.length==2) { |
||
| 217 | if (year > 70) { year=1900+(year-0); } |
||
| 218 | else { year=2000+(year-0); } |
||
| 219 | } |
||
| 220 | } |
||
| 221 | else if (token=="MMM"||token=="NNN"){ |
||
| 222 | month=0; |
||
| 223 | for (var i=0; i<MONTH_NAMES.length; i++) { |
||
| 224 | var month_name=MONTH_NAMES[i]; |
||
| 225 | if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) { |
||
| 226 | if (token=="MMM"||(token=="NNN"&&i>11)) { |
||
| 227 | month=i+1; |
||
| 228 | if (month>12) { month -= 12; } |
||
| 229 | i_val += month_name.length; |
||
| 230 | break; |
||
| 231 | } |
||
| 232 | } |
||
| 233 | } |
||
| 234 | if ((month < 1)||(month>12)){return 0;} |
||
| 235 | } |
||
| 236 | else if (token=="EE"||token=="E"){ |
||
| 237 | for (var i=0; i<DAY_NAMES.length; i++) { |
||
| 238 | var day_name=DAY_NAMES[i]; |
||
| 239 | if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) { |
||
| 240 | i_val += day_name.length; |
||
| 241 | break; |
||
| 242 | } |
||
| 243 | } |
||
| 244 | } |
||
| 245 | else if (token=="MM"||token=="M") { |
||
| 246 | month=_getInt(val,i_val,token.length,2); |
||
| 247 | if(month==null||(month<1)||(month>12)){return 0;} |
||
| 248 | i_val+=month.length;} |
||
| 249 | else if (token=="dd"||token=="d") { |
||
| 250 | date=_getInt(val,i_val,token.length,2); |
||
| 251 | if(date==null||(date<1)||(date>31)){return 0;} |
||
| 252 | i_val+=date.length;} |
||
| 253 | else if (token=="hh"||token=="h") { |
||
| 254 | hh=_getInt(val,i_val,token.length,2); |
||
| 255 | if(hh==null||(hh<1)||(hh>12)){return 0;} |
||
| 256 | i_val+=hh.length;} |
||
| 257 | else if (token=="HH"||token=="H") { |
||
| 258 | hh=_getInt(val,i_val,token.length,2); |
||
| 259 | if(hh==null||(hh<0)||(hh>23)){return 0;} |
||
| 260 | i_val+=hh.length;} |
||
| 261 | else if (token=="KK"||token=="K") { |
||
| 262 | hh=_getInt(val,i_val,token.length,2); |
||
| 263 | if(hh==null||(hh<0)||(hh>11)){return 0;} |
||
| 264 | i_val+=hh.length;} |
||
| 265 | else if (token=="kk"||token=="k") { |
||
| 266 | hh=_getInt(val,i_val,token.length,2); |
||
| 267 | if(hh==null||(hh<1)||(hh>24)){return 0;} |
||
| 268 | i_val+=hh.length;hh--;} |
||
| 269 | else if (token=="mm"||token=="m") { |
||
| 270 | mm=_getInt(val,i_val,token.length,2); |
||
| 271 | if(mm==null||(mm<0)||(mm>59)){return 0;} |
||
| 272 | i_val+=mm.length;} |
||
| 273 | else if (token=="ss"||token=="s") { |
||
| 274 | ss=_getInt(val,i_val,token.length,2); |
||
| 275 | if(ss==null||(ss<0)||(ss>59)){return 0;} |
||
| 276 | i_val+=ss.length;} |
||
| 277 | else if (token=="a") { |
||
| 278 | if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";} |
||
| 279 | else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";} |
||
| 280 | else {return 0;} |
||
| 281 | i_val+=2;} |
||
| 282 | else { |
||
| 283 | if (val.substring(i_val,i_val+token.length)!=token) {return 0;} |
||
| 284 | else {i_val+=token.length;} |
||
| 285 | } |
||
| 286 | } |
||
| 287 | // If there are any trailing characters left in the value, it doesn't match |
||
| 288 | if (i_val != val.length) { return 0; } |
||
| 289 | // Is date valid for month? |
||
| 290 | if (month==2) { |
||
| 291 | // Check for leap year |
||
| 292 | if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year |
||
| 293 | if (date > 29){ return 0; } |
||
| 294 | } |
||
| 295 | else { if (date > 28) { return 0; } } |
||
| 296 | } |
||
| 297 | if ((month==4)||(month==6)||(month==9)||(month==11)) { |
||
| 298 | if (date > 30) { return 0; } |
||
| 299 | } |
||
| 300 | // Correct hours value |
||
| 301 | if (hh<12 && ampm=="PM") { hh=hh-0+12; } |
||
| 302 | else if (hh>11 && ampm=="AM") { hh-=12; } |
||
| 303 | var newdate=new Date(year,month-1,date,hh,mm,ss); |
||
| 304 | return newdate; |
||
| 305 | } |
||
| 306 | |||
| 307 | // ------------------------------------------------------------------ |
||
| 308 | // parseDate( date_string [, prefer_euro_format] ) |
||
| 309 | // |
||
| 310 | // This function takes a date string and tries to match it to a |
||
| 311 | // number of possible date formats to get the value. It will try to |
||
| 312 | // match against the following international formats, in this order: |
||
| 313 | // y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d |
||
| 314 | // M/d/y M-d-y M.d.y MMM-d M/d M-d |
||
| 315 | // d/M/y d-M-y d.M.y d-MMM d/M d-M |
||
| 316 | // A second argument may be passed to instruct the method to search |
||
| 317 | // for formats like d/M/y (european format) before M/d/y (American). |
||
| 318 | // Returns a Date object or null if no patterns match. |
||
| 319 | // ------------------------------------------------------------------ |
||
| 320 | function parseDate(val) { |
||
| 321 | var preferEuro=(arguments.length==2)?arguments[1]:false; |
||
| 322 | generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d'); |
||
| 323 | monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d'); |
||
| 324 | dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M'); |
||
| 325 | var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst'); |
||
| 326 | var d=null; |
||
| 327 | for (var i=0; i<checkList.length; i++) { |
||
| 328 | var l=window[checkList[i]]; |
||
| 329 | for (var j=0; j<l.length; j++) { |
||
| 330 | d=getDateFromFormat(val,l[j]); |
||
| 331 | if (d!=0) { return new Date(d); } |
||
| 332 | } |
||
| 333 | } |
||
| 334 | return null; |
||
| 335 | } |
||
| 336 |