1 /** @namespace Functions for working with dates <br /> 2 * See {@link http://php.net/strftime} for formatting options. 3 */ 4 puredom.date = /** @lends puredom.date */ { 5 6 /** Returns the current timestamp, in milliseconds. 7 * @function 8 * @returns {Number} timestamp 9 */ 10 now : ( 11 Date.now ? function() { 12 return Date.now(); 13 } : function() { 14 return +new Date(); 15 } 16 ), 17 18 19 /** Create a date, optionally from a string.<br /> 20 * This is a wrapper on new Date(str), adding support for more date formats and smoothing out differences between browsers. 21 * @param {String} [str=now] A date string, parsed and used to set the initial date. 22 * @returns {Date} a new date object. 23 */ 24 create : function(str) { 25 var date; 26 if (str) { 27 str = (str+'').replace(/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})T([0-9]{2})\:([0-9]{2})\:([0-9]{2})\.[0-9]{3}Z$/, '$1/$2/$3 $4:$5:$6'); 28 date = new Date(str); 29 } 30 else { 31 date = new Date(); 32 } 33 return date; 34 }, 35 36 37 /** Parse a string with the given format into a Date object. 38 * @param {String} str A date string to parse 39 * @param {String} [format="%d/%m/%Y"] A date format string. See {@link http://php.net/strftime} for available fields. 40 * @returns {Date|Boolean} the date, or false on failure. 41 */ 42 parse : function(str, format) { 43 format = format || "%d/%m/%Y"; 44 function setHours(hours, pm) { 45 if (pm===false || pm===true) { 46 temp.pm = pm===true; 47 } 48 if (hours || hours===0) { 49 temp.hours = hours; 50 } 51 hours = temp.hours; 52 if (temp.hours<12 && temp.pm) { 53 hours -= 12; 54 } 55 var i = rdate.getDate(); 56 if (temp.hours===12 && temp.pm===false) { 57 if (rdate.getHours()!==0 || typeof pm==='boolean') { 58 rdate.setHours(0); 59 } 60 } 61 else { 62 rdate.setHours(hours); 63 rdate.setDate(i); 64 } 65 } 66 var origStr = str, 67 rdate = new Date(0), 68 temp = {}, 69 weekdays = ['mo','tu','we','th','fr','sa','su'], 70 replacers = { 71 H : [/^[0-9]{1,2}/g, function(e){e=Math.round(e);setHours(e);}], 72 I : [/^[0-9]{1,2}/g, function(e){e=Math.round(e);setHours(e);}], 73 p : [/^[AP]M/gi, function(e){setHours(null, e.toLowerCase()==="pm");}], 74 M : [/^[0-9]{1,2}/g, function(e){rdate.setMinutes(Math.round(e));}], 75 a : [/^(Mon|Tue(s?)|Wed|Thu|Fri|Sat|Sun)/i, function(){}], // dummy 76 A : [/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)/i, function(){}], // dummy 77 78 79 d : [/^[0-9]{1,2}/g, function(e){temp.date=Math.round(e);rdate.setDate(temp.date);}], 80 m : [/^[0-9]{1,2}/g, function(e){temp.month=Math.round(e)-1;rdate.setMonth(temp.month);}], 81 B : [new RegExp('^('+this.months.join("|")+')','gi'), function(e){temp.month=date._getMonthIndex(e);rdate.setMonth(temp.month);}], 82 b : [/^(Jan|Feb|Mar|Apr|May|Jun(e?)|Jul(y?)|Aug|Sep(t?)|Oct|Nov|Dec)/gi, function(e){temp.month=date._getMonthIndex(e);rdate.setMonth(temp.month);}], 83 y : [/^[0-9]{2}/g, function(e){e=Math.round(e)+1900;if(e<1950){e+=100;}rdate.setFullYear(e);}], // wrap 2-digit dates at 1950/2050 84 Y : [/^[0-9]{4}/g, function(e){temp.year=Math.round(e);rdate.setFullYear(temp.year);}] 85 }, 86 index, rep, r; 87 replacers.l = replacers.I; 88 replacers.e = replacers.d; 89 replacers.P = replacers.p; 90 replacers.h = replacers.b; 91 92 /** @ignore */ 93 function rp(e) { 94 rep[1](e); 95 return ''; 96 } 97 98 for (index=0; index<format.length; index++) { 99 if (format.charAt(index)==="%") { 100 rep = null; 101 if (str.charAt(0)===' ' && format.charAt(index)==='%') { 102 str = str.substring(1); 103 } 104 for (r in replacers) { 105 if (replacers.hasOwnProperty(r) && format.substring(index+1, index+1+r.length)===r) { 106 rep = replacers[r]; 107 str = str.replace(rep[0], rp); 108 index += rep.length-1; // advance past the used symbol in format str 109 break; 110 } 111 } 112 } 113 else { 114 if (str.charAt(0)===format.charAt(index)) { 115 str = str.substring(1); 116 } 117 } 118 } 119 120 if (temp.month || temp.month===0) { 121 rdate.setMonth(temp.month); 122 } 123 if (temp.year || temp.year===0) { 124 rdate.setFullYear(temp.year); 125 } 126 127 return rdate; 128 }, 129 130 131 /** Alias of {@link puredom.date.parse} 132 * @see puredom.date.parse 133 * @deprecated 134 * @private 135 */ 136 unformat : function(){return this.parse.apply(this,arguments);}, 137 138 139 /** Get a formatted string representation of a Date object. 140 * @param {String} date A date object to convert 141 * @param {String} [format="%d/%m/%Y"] A date format string. See {@link http://php.net/strftime} for available fields. 142 * @returns {String|Boolean} the formatted date string, or false on failure. 143 */ 144 format : function(date, format) { 145 format = format || "%d/%m/%Y"; 146 147 if (!date || date.constructor!==Date || !date.toDateString) { 148 return false; 149 } 150 151 var dateStr = date.toDateString(); 152 if (!dateStr || dateStr.toLowerCase()==="invalid date") { 153 return false; 154 } 155 156 if (dateStr==='NaN') { // only trips in IE ("3 is not an object") 157 return false; 158 } 159 160 var dateParts = dateStr.split(" "), 161 hours = date.getHours(), 162 hv = ((hours+11)%12)+1, 163 m = date.getMonth()+1, 164 replacers = { 165 H : hours, // 24 hour time 166 I : (hv<10?"0":"") + hv, // 12 hour time, leading 0 167 l : hv, // 12 hour time 168 p : hours>11?"PM":"AM", 169 P : hours>11?"pm":"am", 170 M : (date.getMinutes()<10?"0":"") + date.getMinutes(), 171 S : (date.getSeconds()<10?"0":"") + date.getSeconds(), // seconds 172 a : dateParts[0], 173 A : this.weekdays[date.getDay()], 174 d : dateParts[2], 175 e : Math.round(dateParts[2]), 176 m : (m<10?"0":"") + m, 177 B : this.months[Math.round(dateParts[1])], 178 b : dateParts[1], 179 h : dateParts[1], 180 y : dateParts[3].substring(2), 181 Y : dateParts[3] 182 }; 183 184 return format.replace(/%[HIlpPMSaAdemBbhyY]/gm, function(s) { 185 var v = replacers[s.charAt(1)+'']; 186 return (v || v===0 || v===false) ? v : s; 187 }); 188 }, 189 190 191 /** @private */ 192 _getMonthIndex : function(m){ 193 m = m.substring(0,3).toLowerCase(); 194 for (var x=0; x<this.months.length; x++) { 195 if (this.months[x].substring(0,3).toLowerCase()===m) { 196 return x; 197 } 198 } 199 return -1; 200 }, 201 202 203 /** Weekday names 204 * @type Array(String) 205 */ 206 weekdays : ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], 207 208 209 /** Month names 210 * @type Array(String) 211 */ 212 months : ["January","February","March","April","May","June","July","August","September","October","November","December"] 213 214 };