UNPKG

@luminati-io/luminati-proxy

Version:

A configurable local proxy for luminati.io

695 lines (669 loc) 24.5 kB
// LICENSE_CODE ZON ISC 'use strict'; /*jslint node:true, browser:true*/ (function(){ var define; var is_node = typeof module=='object' && module.exports && module.children; var is_node_ff = typeof module=='object' && module.exports; if (!is_node_ff) define = self.define; else define = require('./require_node.js').define(module, '../'); define([], function(){ var E = date_get; E.sec = { NANO: 1e-9, MS: 1e-3, SEC: 1, MIN: 60, HOUR: 60*60, DAY: 24*60*60, WEEK: 7*24*60*60, MONTH: 30*24*60*60, YEAR: 365*24*60*60, }; E.ms = {}; for (var key in E.sec) E.ms[key] = E.sec[key]*1000; var ms = E.ms; function pad(num, size){ return ('000'+num).slice(-size); } E.ms_to_dur = function(_ms){ var s = '', sec = Math.floor(_ms/1000); if (sec<0) { s += '-'; sec = -sec; } var days = Math.floor(sec/(60*60*24)); sec -= days*60*60*24; var hours = Math.floor(sec/(60*60)); sec -= hours*60*60; var mins = Math.floor(sec/60); sec -= mins*60; if (days) s += days + ' ' + (days>1 ? 'Days' : 'Day') + ' '; return s+pad(hours, 2)+':'+pad(mins, 2)+':'+pad(sec, 2); }; E.round_dur = function(dur, precision){ return !precision ? Math.round(dur) : precision*Math.round(dur/precision); }; E.dur_to_str = function(dur, opt){ opt = opt||{}; var parts = []; dur = E.round_dur(+dur, opt.precision); function chop(period, name){ if (dur<period) return; var number = Math.floor(dur/period); parts.push(number+name); dur -= number*period; } chop(ms.YEAR, 'y'); chop(ms.MONTH, 'mo'); if (opt.week) chop(ms.WEEK, 'w'); chop(ms.DAY, 'd'); chop(ms.HOUR, 'h'); chop(ms.MIN, 'min'); chop(ms.SEC, 's'); if (dur) parts.push(dur+'ms'); if (!parts.length) return '0s'; return parts.slice(0, opt.units||parts.length).join(opt.sep||''); }; E.monotonic = undefined; E.init = function(){ var adjust, last; if (typeof window=='object' && window.performance && window.performance.now) { // 10% slower than Date.now, but always monotonic adjust = Date.now()-window.performance.now(); E.monotonic = function(){ return window.performance.now()+adjust; }; } else if (is_node && !global.mocha_running) { var now_fn = function(){ var data = process.hrtime(); var seconds = data[0], nanos = data[1]; return Math.floor(seconds * E.ms.SEC + nanos * E.ms.NANO); }; adjust = Date.now()-now_fn(); E.monotonic = function(){ return now_fn()+adjust; }; } else { last = adjust = 0; E.monotonic = function(){ var now = Date.now()+adjust; if (now>=last) return last = now; adjust += last-now; return last; }; } }; E.init(); E.str_to_dur = function(str, opt){ opt = opt||{}; var month = 'mo|mon|months?'; if (opt.short_month) month +='|m'; var m = str.replace(/ /g, '').match(new RegExp('^(([0-9]+)y(ears?)?)?' +'(([0-9]+)('+month+'))?(([0-9]+)w(eeks?)?)?(([0-9]+)d(ays?)?)?' +'(([0-9]+)h(ours?)?)?(([0-9]+)(min|minutes?))?' +'(([0-9]+)s(ec|econds?)?)?(([0-9]+)ms(ec)?)?$', 'i')); if (!m) return; return ms.YEAR*(+m[2]||0)+ms.MONTH*(+m[5]||0)+ms.WEEK*(+m[8]||0) +ms.DAY*(+m[11]||0)+ms.HOUR*(+m[14]||0)+ms.MIN*(+m[17]||0) +ms.SEC*(+m[20]||0)+(+m[23]||0); }; E.months_long = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; E.months_short = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; var months_short_lc = E.months_short.map(function(m){ return m.toLowerCase(); }); E.days_long = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; E.days_short = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; var days_short_lc = E.days_short.map(function(d){ return d.toLowerCase(); }); var days_long_lc = E.days_long.map(function(d){ return d.toLowerCase(); }); E.locale = {months_long: E.months_long, months_short: E.months_short, days_long: E.days_long, days_short: E.days_short, AM: 'AM', PM: 'PM'}; E.get = date_get; function date_get(d, _new){ var y, mon, day, H, M, S, _ms; if (d==null) return new Date(); if (d instanceof Date) return _new ? new Date(d) : d; if (typeof d=='string') { var m; d = d.trim(); // check for ISO/SQL/JDate date if (m = /^((\d\d\d\d)-(\d\d)-(\d\d)|(\d\d?)-([A-Za-z]{3})-(\d\d(\d\d)?))\s*([\sT](\d\d):(\d\d)(:(\d\d)(\.(\d\d\d))?)?Z?)?$/ .exec(d)) { H = +m[10]||0; M = +m[11]||0; S = +m[13]||0; _ms = +m[15]||0; if (m[2]) // SQL or ISO date { y = +m[2]; mon = +m[3]; day = +m[4]; if (!y && !mon && !day && !H && !M && !S && !_ms) return new Date(NaN); return new Date(Date.UTC(y, mon-1, day, H, M, S, _ms)); } if (m[5]) // jdate { y = +m[7]; mon = months_short_lc.indexOf(m[6].toLowerCase())+1; day = +m[5]; if (m[7].length==2) { y = +y; y += y>=70 ? 1900 : 2000; } return new Date(Date.UTC(y, mon-1, day, H, M, S, _ms)); } // cannot reach here } // check for string timestamp if (/^\d+$/.test(d)) return new Date(+d); // else might be parsed as non UTC! return new Date(d); } if (typeof d=='number') return new Date(d); throw new TypeError('invalid date '+d); } E.to_sql_ms = function(d){ d = E.get(d); if (isNaN(d)) return '0000-00-00 00:00:00.000'; return pad(d.getUTCFullYear(), 4)+'-'+pad(d.getUTCMonth()+1, 2) +'-'+pad(d.getUTCDate(), 2) +' '+pad(d.getUTCHours(), 2)+':'+pad(d.getUTCMinutes(), 2) +':'+pad(d.getUTCSeconds(), 2) +'.'+pad(d.getUTCMilliseconds(), 3); }; E.to_sql_sec = function(d){ return E.to_sql_ms(d).slice(0, -4); }; E.to_sql = function(d){ return E.to_sql_ms(d).replace(/( 00:00:00)?....$/, ''); }; E.from_sql = E.get; E.to_month_short = function(d){ d = E.get(d); return E.months_short[d.getUTCMonth()]; }; E.to_month_long = function(d){ d = E.get(d); return E.months_long[d.getUTCMonth()]; }; // timestamp format (used by tickets, etc). dates before 2000 not supported E.to_jdate = function(d){ d = E.get(d); return (pad(d.getUTCDate(), 2)+'-'+E.months_short[d.getUTCMonth()] +'-'+pad(d.getUTCFullYear()%100, 2)+' '+pad(d.getUTCHours(), 2)+ ':'+pad(d.getUTCMinutes(), 2)+':'+pad(d.getUTCSeconds(), 2)) .replace(/( 00:00)?:00$/, ''); }; // used in log file names E.to_log_file = function(d){ d = E.get(d); return d.getUTCFullYear()+pad(d.getUTCMonth()+1, 2)+pad(d.getUTCDate(), 2) +'_'+pad(d.getUTCHours(), 2)+pad(d.getUTCMinutes(), 2) +pad(d.getUTCSeconds(), 2); }; E.from_log_file = function(d){ var m = d.match(/^(\d{4})(\d{2})(\d{2})_(\d{2})(\d{2})(\d{2})$/); if (!m) return; return new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6])); }; // zerr compatible timestamp format E.to_log_ms = function(d){ return E.to_sql_ms(d).replace(/-/g, '.'); }; E.from_rcs = function(d){ var m = d.match(/^(\d{4})\.(\d{2})\.(\d{2})\.(\d{2})\.(\d{2})\.(\d{2})$/); if (!m) return; return new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6])); }; E.to_rcs = function(d){ return E.to_sql_sec(d).replace(/[-: ]/g, '.'); }; E.align = function(d, align){ d = E.get(d, 1); switch (align.toUpperCase()) { case 'MS': break; case 'SEC': d.setUTCMilliseconds(0); break; case 'MIN': d.setUTCSeconds(0, 0); break; case 'HOUR': d.setUTCMinutes(0, 0, 0); break; case 'DAY': d.setUTCHours(0, 0, 0, 0); break; case 'WEEK': d.setUTCDate(d.getUTCDate()-d.getUTCDay()); d.setUTCHours(0, 0, 0, 0); break; case 'MONTH': d.setUTCDate(1); d.setUTCHours(0, 0, 0, 0); break; case 'YEAR': d.setUTCMonth(0, 1); d.setUTCHours(0, 0, 0, 0); break; default: throw new Error('invalid align '+align); } return d; }; E.add = function(d, dur){ d = E.get(d, 1); dur = normalize_dur(dur); if (dur.year) d.setUTCFullYear(d.getUTCFullYear()+dur.year); if (dur.month) d.setUTCMonth(d.getUTCMonth()+dur.month); ['day', 'hour', 'min', 'sec', 'ms'].forEach(function(k){ if (dur[k]) d.setTime(+d+dur[k]*ms[k.toUpperCase()]); }); return d; }; function normalize_dur(dur){ var aliases = { years: 'year', months: 'month', days: 'day', hours: 'hour', minutes: 'min', seconds: 'sec', minute: 'min', mins: 'min', second: 'sec', secs: 'sec', y: 'year', mo: 'month', d: 'day', h: 'hour', m: 'min', s: 'sec', }; var norm = {}; for (var k in dur) norm[aliases[k]||k] = dur[k]; return norm; } E.describe_interval = function(_ms, decimals){ var rmult = Math.pow(10, decimals||0); return _ms<2*ms.MIN ? Math.round(_ms/ms.SEC*rmult)/rmult+' sec' : _ms<2*ms.HOUR ? Math.round(_ms/ms.MIN*rmult)/rmult+' min' : _ms<2*ms.DAY ? Math.round(_ms/ms.HOUR*rmult)/rmult+' hours' : _ms<2*ms.WEEK ? Math.round(_ms/ms.DAY*rmult)/rmult+' days' : _ms<2*ms.MONTH ? Math.round(_ms/ms.WEEK*rmult)/rmult+' weeks' : _ms<2*ms.YEAR ? Math.round(_ms/ms.MONTH*rmult)/rmult+' months' : Math.round(_ms/ms.YEAR*rmult)/rmult+' years'; }; E.time_ago = function(d, until_date){ var _ms = E.get(until_date)-E.get(d); if (_ms<ms.SEC) return 'right now'; return E.describe_interval(_ms)+' ago'; }; E.ms_to_str = function(_ms){ var s = ''+_ms; return s.length<=3 ? s+'ms' : s.slice(0, -3)+'.'+s.slice(-3)+'s'; }; E.parse = function(text, opt){ opt = opt||{}; if (opt.fmt) return E.strptime(text, opt.fmt); var d, a, i, v, _v, dir, _dir, amount, now = opt.now; now = !now ? new Date() : new Date(now); text = text.replace(/\s+/g, ' ').trim().toLowerCase(); if (!text) return; if (text=='now') return now; if (!isNaN(d = E.get(text))) return d; d = now; a = text.split(' '); dir = a.includes('ago') ? -1 : a.includes('last') ? -1 : a.includes('next') ? 1 : undefined; for (i=0; i<a.length; i++) { v = a[i]; if (/^(ago|last|next)$/.test(v)); else if (v=='today') d = E.align(d, 'DAY'); else if (v=='yesterday') d = E.align(+d-ms.DAY, 'DAY'); else if (v=='tomorrow') d = E.align(+d+ms.DAY, 'DAY'); else if ((_v = days_short_lc.indexOf(v))>=0) d = new Date(+E.align(d, 'WEEK')+_v*ms.DAY+(dir||0)*ms.WEEK); else if ((_v = days_long_lc.indexOf(v))>=0) d = new Date(+E.align(d, 'WEEK')+_v*ms.DAY+(dir||0)*ms.WEEK); else if (_v = /^([+-]?\d+)(?:([ymoinwdhs]+)(\d.*)?)?$/.exec(v)) { if (amount!==undefined) return; amount = dir!==undefined ? Math.abs(+_v[1]) : +_v[1]; if (_v[2]) { a.splice(i+1, 0, _v[2]); if (_v[3]) a.splice(i+2, 0, _v[3]); } continue; } else if (/^([ywdhs]|years?|months?|mon?|weeks?|days?|hours?|minutes?|min|seconds?|sec)$/.test(v)) { _v = v[0]=='m' && v[1]=='i' ? ms.MIN : v[0]=='y' ? ms.YEAR : v[0]=='m' && v[1]=='o' ? ms.MONTH : v[0]=='w' ? ms.WEEK : v[0]=='d' ? ms.DAY : v[0]=='h' ? ms.HOUR : ms.SEC; amount = amount===undefined ? 1 : amount; _dir = dir===undefined ? opt.dir||1 : dir; if (_v==ms.MONTH) d.setUTCMonth(d.getUTCMonth()+_dir*amount); else if (_v==ms.YEAR) d.setUTCFullYear(d.getUTCFullYear()+_dir*amount); else d = new Date(+d+_v*amount*_dir); amount = undefined; } else return; if (amount!==undefined) return; } if (amount!==undefined) return; return d; }; E.strptime = function(str, fmt){ function month(m){ return months_short_lc.indexOf(m.toLowerCase()); } var parse = { '%': ['%', function(){}, 0], a: ['[a-z]+', function(m){}, 0], A: ['[a-z]+', function(m){}, 0], b: ['[a-z]+', function(m){ d.setUTCMonth(month(m)); }, 2], B: ['[a-z]+', function(m){ d.setUTCMonth(month(m)); }, 2], y: ['[0-9]{2}', function(m){ d.setUTCFullYear(+m+(m<70 ? 2000 : 1900)); }, 1], Y: ['[0-9]{4}', function(m){ d.setUTCFullYear(+m); }, 1], m: ['[0-9]{0,2}', function(m){ d.setUTCMonth(+m-1); }, 2], d: ['[0-9]{0,2}', function(m){ d.setUTCDate(+m); }, 3], H: ['[0-9]{0,2}', function(m){ d.setUTCHours(+m); }, 4], M: ['[0-9]{0,2}', function(m){ d.setUTCMinutes(+m); }, 5], S: ['[0-9]{0,2}', function(m){ d.setUTCSeconds(+m); }, 6], s: ['[0-9]+', function(m){ d = new Date(+m); }, 0], L: ['[0-9]{0,3}', function(m){ d.setUTCMilliseconds(+m); }, 7], z: ['[+-][0-9]{4}', function(m){ var timezone = +m.slice(0, 3)*3600+m.slice(3, 5)*60; d = new Date(+d-timezone*1000); }, 8], Z: ['[a-z]{0,3}[+-][0-9]{2}:?[0-9]{2}|[a-z]{1,3}', function(m){ m = /^([a-z]{0,3})(?:([+-][0-9]{2}):?([0-9]{2}))?$/i.exec(m); if (m[1]=='Z' || m[1]=='UTC') return; var timezone = +m[2]*3600+m[3]*60; d = new Date(+d-timezone*1000); }, 8], I: ['[0-9]{0,2}', function(m){ d.setUTCHours(+m); }, 4], p: ['AM|PM', function(m){ if (d.getUTCHours()==12) d.setUTCHours(d.getUTCHours()-12); if (m.toUpperCase()=='PM') d.setUTCHours(d.getUTCHours()+12); }, 9], }; var ff = []; var ff_idx = []; var re = new RegExp('^\\s*'+fmt.replace(/%(?:([a-zA-Z%]))/g, function(_, fd) { var d = parse[fd]; if (!d) throw Error('Unknown format descripter: '+fd); ff_idx[d[2]] = ff.length; ff.push(d[1]); return '('+d[0]+')'; })+'\\s*$', 'i'); var matched = str.match(re); if (!matched) return; var d = new Date(0); for (var i=0; i<ff_idx.length; i++) { var idx = ff_idx[i]; var fun = ff[idx]; if (fun) fun(matched[idx+1]); } return d; }; // tz in format shh:mm (for exmpl +01:00, -03:45) E.apply_tz = function(date, tz, opt){ if (!date) return date; date = E.get(date); tz = (tz||E.local_tz).replace(':', ''); opt = opt||{}; var timezone = +tz.slice(1, 3)*E.ms.HOUR+tz.slice(3, 5)*E.ms.MIN; var sign = tz.slice(0, 1) == '+' ? 1 : -1; if (opt.inverse) sign *= -1; return new Date(date.getTime()+sign*timezone); }; var utc_local = { local: { getSeconds: function(d){ return d.getSeconds(); }, getMinutes: function(d){ return d.getMinutes(); }, getHours: function(d){ return d.getHours(); }, getDay: function(d){ return d.getDay(); }, getDate: function(d){ return d.getDate(); }, getMonth: function(d){ return d.getMonth(); }, getFullYear: function(d){ return d.getFullYear(); }, getYearBegin: function(d){ return new Date(d.getFullYear(), 0, 1); } }, utc: { getSeconds: function(d){ return d.getUTCSeconds(); }, getMinutes: function(d){ return d.getUTCMinutes(); }, getHours: function(d){ return d.getUTCHours(); }, getDay: function(d){ return d.getUTCDay(); }, getDate: function(d){ return d.getUTCDate(); }, getMonth: function(d){ return d.getUTCMonth(); }, getFullYear: function(d){ return d.getUTCFullYear(); }, getYearBegin: function(d){ return new Date(Date.UTC( d.getUTCFullYear(), 0, 1)); } } }; E.strftime = function(fmt, d, opt){ function hours12(hours){ return hours==0 ? 12 : hours>12 ? hours-12 : hours; } function ord_str(n){ var i = n % 10, ii = n % 100; if (ii>=11 && ii<=13 || i==0 || i>=4) return 'th'; switch (i) { case 1: return 'st'; case 2: return 'nd'; case 3: return 'rd'; } } function week_num(l, _d, first_weekday){ // This works by shifting the weekday back by one day if we // are treating Monday as the first day of the week. var wday = l.getDay(_d); if (first_weekday=='monday') wday = wday==0 /* Sunday */ ? wday = 6 : wday-1; var yday = (_d-l.getYearBegin(_d))/ms.DAY; return Math.floor((yday + 7 - wday)/7); } // Default padding is '0' and default length is 2, both are optional. function padx(n, padding, length){ // padx(n, <length>) if (typeof padding=='number') { length = padding; padding = '0'; } // Defaults handle padx(n) and padx(n, <padding>) if (padding===undefined) padding = '0'; length = length||2; var s = ''+n; // padding may be an empty string, don't loop forever if it is if (padding) for (; s.length<length; s = padding + s); return s; } opt = opt||{}; d = E.get(d); var locale = opt.locale||E.locale; var formats = locale.formats||{}; var tz = opt.timezone; var utc = opt.utc!==undefined ? opt.utc : opt.local!==undefined ? !opt.local : true; if (tz!=null) { utc = true; // ISO 8601 format timezone string, [-+]HHMM // Convert to the number of minutes and it'll be applied to the date // below. if (typeof tz=='string') { var sign = tz[0]=='-' ? -1 : 1; var hours = parseInt(tz.slice(1, 3), 10); var mins = parseInt(tz.slice(3, 5), 10); tz = sign*(60*hours+mins); } if (typeof tz=='number') d = new Date(+d+tz*60000); } var l = utc ? utc_local.utc : utc_local.local; // Most of the specifiers supported by C's strftime, and some from Ruby. // Some other syntax extensions from Ruby are supported: %-, %_, and %0 // to pad with nothing, space, or zero (respectively). function replace(_fmt){ return _fmt.replace(/%([-_0]?.)/g, function(_, c){ var mod, padding, day; if (c.length==2) { mod = c[0]; if (mod=='-') // omit padding padding = ''; else if (mod=='_') // pad with space padding = ' '; else if (mod=='0') // pad with zero padding = '0'; else // unrecognized, return the format return _; c = c[1]; } switch (c) { // Examples for new Date(0) in GMT case 'A': return locale.days_long[l.getDay(d)]; // 'Thursday' case 'a': return locale.days_short[l.getDay(d)]; // 'Thu' case 'B': return locale.months_long[l.getMonth(d)]; // 'January' case 'b': return locale.months_short[l.getMonth(d)]; // 'Jan' case 'C': // '19' return padx(Math.floor(l.getFullYear(d)/100), padding); case 'D': return replace(formats.D || '%m/%d/%y'); // '01/01/70' case 'd': return padx(l.getDate(d), padding); // '01' case 'e': return l.getDate(d); // '01' case 'F': return replace(formats.F || '%Y-%m-%d'); // '1970-01-01' case 'H': return padx(l.getHours(d), padding); // '00' case 'h': return locale.months_short[l.getMonth(d)]; // 'Jan' case 'I': return padx(hours12(l.getHours(d)), padding); // '12' case 'j': // '000' day = Math.ceil((+d-l.getYearBegin(d))/(1000*60*60*24)); return pad(day, 3); case 'k': // ' 0' return padx(l.getHours(d), padding===undefined ? ' ' : padding); case 'L': return pad(Math.floor(d.getMilliseconds()), 3); // '000' case 'l': // '12' return padx(hours12(l.getHours(d)), padding===undefined ? ' ' : padding); case 'M': return padx(l.getMinutes(d), padding); // '00' case 'm': return padx(l.getMonth(d)+1, padding); // '01' case 'n': return '\n'; // '\n' case 'o': return ''+l.getDate(d)+ord_str(l.getDate(d)); // '1st' case 'P': // 'am' return (l.getHours(d)<12 ? locale.AM : locale.PM).toLowerCase(); case 'p': return l.getHours(d)<12 ? locale.AM : locale.PM; // 'AM' case 'R': return replace(formats.R || '%H:%M'); // '00:00' case 'r': return replace(formats.r || '%I:%M:%S %p'); // '12:00:00 AM' case 'S': return padx(l.getSeconds(d), padding); // '00' case 's': return Math.floor(+d/1000); // '0' case 'T': return replace(formats.T || '%H:%M:%S'); // '00:00:00' case 't': return '\t'; // '\t' case 'U': return padx(week_num(l, d, 'sunday'), padding); // '00' case 'u': // '4' day = l.getDay(d); // 1 - 7, Monday is first day of the week return day==0 ? 7 : day; case 'v': return replace(formats.v || '%e-%b-%Y'); // '1-Jan-1970' case 'W': return padx(week_num(l, d, 'monday'), padding); // '00' case 'w': return l.getDay(d); // '4'. 0 Sunday - 6 Saturday case 'Y': return l.getFullYear(d); // '1970' case 'y': return (''+l.getFullYear(d)).slice(-2); // '70' case 'Z': // 'GMT' if (utc) return 'GMT'; var tz_string = d.toString().match(/\((\w+)\)/); return tz_string && tz_string[1] || ''; case 'z': // '+0000' if (utc) return '+0000'; var off = typeof tz=='number' ? tz : -d.getTimezoneOffset(); return (off<0 ? '-' : '+')+pad(Math.abs(Math.trunc(off/60)), 2)+ pad(off%60, 2); default: return c; } }); } return replace(fmt); }; E.local_tz = E.strftime('%z', E.get(), {utc: false}); // For a string like '11:00-23:30', returns a function that checks whether a // given date (moment in time) belongs to the set. // Syntax notes: // * ':00' is optional: '11-23' // * several intervals: '12-14 16-18' // * '10-12' includes exact 10:00 but excludes exact 12:00 // * 24:00 is the same as 0:00, 25:00 is the same as 1:00, etc // * intervals wrap around midnight: '23-7' is the same as '23-24 0-7' // * therefore, '0-0' and '0-24' include all times // * all times are assumed in UTC E.compile_schedule = function(expr){ var re = /^(\d\d?)(?::(\d\d?))?-(\d\d?)(?::(\d\d?))?$/; var parts = expr.split(/\s+/); var intervals = []; for (var i = 0; i<parts.length; i++) { if (!parts[i]) continue; var m = re.exec(parts[i]); if (!m) throw new Error('Schedule syntax error: '+expr); var from = m[1]*ms.HOUR, to = m[3]*ms.HOUR; if (m[2]) from += m[2]*ms.MIN; if (m[4]) to += m[4]*ms.MIN; intervals.push({from: from%ms.DAY, to: to%ms.DAY}); } return function(d){ var t = E.get(d) % ms.DAY; for (var j = 0; j<intervals.length; j++) { var interval = intervals[j]; if (interval.from<interval.to) { if (t>=interval.from && t<interval.to) return true; } else { if (t<interval.to || t>=interval.from) return true; } } return false; }; }; E.timezone_offset = function(tz, dt){ dt = dt || E.get(); tz = dt.toLocaleString('en', {timeZone: tz, timeStyle: 'long'}) .split(' ').slice(-1)[0]; var dt_str = dt.toString(); var offset = Date.parse(dt_str+' '+tz)-Date.parse(dt_str+' UTC'); return offset/ms.MIN; }; return E; }); }());