var func = {}; func.urlEncode = function(str) { str = (str + '') .toString(); // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following. return encodeURIComponent(str) .replace(/!/g, '%21') .replace(/'/g, '%27') .replace(/\(/g, '%28') . replace(/\)/g, '%29') .replace(/\*/g, '%2A') .replace(/%20/g, '+'); }; func.generateHash = function(length) { if (!length) { length = 32; } var string = '', hash_arr = 'abcdefghijklmnopqrstuvwxyz0123456789'; for (var i = 0; i < length; ++i) { var word_i = func.rand(0, hash_arr.length - 1); string += hash_arr[word_i] } return string; }; func.rand = function(min, max) { var argc = arguments.length; if (argc === 0) { min = 0; max = 2147483647; } else if (argc === 1) { throw new Error('Warning: rand() expects exactly 2 parameters, 1 given'); } return Math.floor(Math.random() * (max - min + 1)) + min; }; func.strtotime = function(text, now) { var parsed, match, today, year, date, days, ranges, len, times, regex, i, fail = false; if (!text) { return fail; } // Unecessary spaces text = text.replace(/^\s+|\s+$/g, '') .replace(/\s{2,}/g, ' ') .replace(/[\t\r\n]/g, '') .toLowerCase(); match = text.match( /^(\d{1,4})([\-\.\/\:])(\d{1,2})([\-\.\/\:])(\d{1,4})(?:\s(\d{1,2}):(\d{2})?:?(\d{2})?)?(?:\s([A-Z]+)?)?$/); if (match && match[2] === match[4]) { if (match[1] > 1901) { switch (match[2]) { case '-': { // YYYY-M-D if (match[3] > 12 || match[5] > 31) { return fail; } return new Date(match[1], parseInt(match[3], 10) - 1, match[5], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } case '.': { // YYYY.M.D is not parsed by strtotime() return fail; } case '/': { // YYYY/M/D if (match[3] > 12 || match[5] > 31) { return fail; } return new Date(match[1], parseInt(match[3], 10) - 1, match[5], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } } } else if (match[5] > 1901) { switch (match[2]) { case '-': { // D-M-YYYY if (match[3] > 12 || match[1] > 31) { return fail; } return new Date(match[5], parseInt(match[3], 10) - 1, match[1], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } case '.': { // D.M.YYYY if (match[3] > 12 || match[1] > 31) { return fail; } return new Date(match[5], parseInt(match[3], 10) - 1, match[1], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } case '/': { // M/D/YYYY if (match[1] > 12 || match[3] > 31) { return fail; } return new Date(match[5], parseInt(match[1], 10) - 1, match[3], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } } } else { switch (match[2]) { case '-': { // YY-M-D if (match[3] > 12 || match[5] > 31 || (match[1] < 70 && match[1] > 38)) { return fail; } year = match[1] >= 0 && match[1] <= 38 ? +match[1] + 2000 : match[1]; return new Date(year, parseInt(match[3], 10) - 1, match[5], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } case '.': { // D.M.YY or H.MM.SS if (match[5] >= 70) { // D.M.YY if (match[3] > 12 || match[1] > 31) { return fail; } return new Date(match[5], parseInt(match[3], 10) - 1, match[1], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } if (match[5] < 60 && !match[6]) { // H.MM.SS if (match[1] > 23 || match[3] > 59) { return fail; } today = new Date(); return new Date(today.getFullYear(), today.getMonth(), today.getDate(), match[1] || 0, match[3] || 0, match[5] || 0, match[9] || 0) / 1000; } // invalid format, cannot be parsed return fail; } case '/': { // M/D/YY if (match[1] > 12 || match[3] > 31 || (match[5] < 70 && match[5] > 38)) { return fail; } year = match[5] >= 0 && match[5] <= 38 ? +match[5] + 2000 : match[5]; return new Date(year, parseInt(match[1], 10) - 1, match[3], match[6] || 0, match[7] || 0, match[8] || 0, match[9] || 0) / 1000; } case ':': { // HH:MM:SS if (match[1] > 23 || match[3] > 59 || match[5] > 59) { return fail; } today = new Date(); return new Date(today.getFullYear(), today.getMonth(), today.getDate(), match[1] || 0, match[3] || 0, match[5] || 0) / 1000; } } } } // other formats and "now" should be parsed by Date.parse() if (text === 'now') { return now === null || isNaN(now) ? new Date() .getTime() / 1000 | 0 : now | 0; } if (!isNaN(parsed = Date.parse(text))) { return parsed / 1000 | 0; } date = now ? new Date(now * 1000) : new Date(); days = { 'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6 }; ranges = { 'yea': 'FullYear', 'mon': 'Month', 'day': 'Date', 'hou': 'Hours', 'min': 'Minutes', 'sec': 'Seconds' }; function lastNext(type, range, modifier) { var diff, day = days[range]; if (typeof day !== 'undefined') { diff = day - date.getDay(); if (diff === 0) { diff = 7 * modifier; } else if (diff > 0 && type === 'last') { diff -= 7; } else if (diff < 0 && type === 'next') { diff += 7; } date.setDate(date.getDate() + diff); } } function process(val) { var splt = val.split(' '), // Todo: Reconcile this with regex using \s, taking into account browser issues with split and regexes type = splt[0], range = splt[1].substring(0, 3), typeIsNumber = /\d+/.test(type), ago = splt[2] === 'ago', num = (type === 'last' ? -1 : 1) * (ago ? -1 : 1); if (typeIsNumber) { num *= parseInt(type, 10); } if (ranges.hasOwnProperty(range) && !splt[1].match(/^mon(day|\.)?$/i)) { return date['set' + ranges[range]](date['get' + ranges[range]]() + num); } if (range === 'wee') { return date.setDate(date.getDate() + (num * 7)); } if (type === 'next' || type === 'last') { lastNext(type, range, num); } else if (!typeIsNumber) { return false; } return true; } times = '(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec' + '|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?' + '|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)'; regex = '([+-]?\\d+\\s' + times + '|' + '(last|next)\\s' + times + ')(\\sago)?'; match = text.match(new RegExp(regex, 'gi')); if (!match) { return fail; } for (i = 0, len = match.length; i < len; i++) { if (!process(match[i])) { return fail; } } // ECMAScript 5 only // if (!match.every(process)) // return false; return (date.getTime() / 1000); }