UNPKG

hebcal

Version:

An easy to use, richly-featured, perpetual Jewish Calendar API

1,712 lines (1,451 loc) 120 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. var objectCreate = Object.create || objectCreatePolyfill var objectKeys = Object.keys || objectKeysPolyfill var bind = Function.prototype.bind || functionBindPolyfill function EventEmitter() { if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { this._events = objectCreate(null); this._eventsCount = 0; } this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. var defaultMaxListeners = 10; var hasDefineProperty; try { var o = {}; if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); hasDefineProperty = o.x === 0; } catch (err) { hasDefineProperty = false } if (hasDefineProperty) { Object.defineProperty(EventEmitter, 'defaultMaxListeners', { enumerable: true, get: function() { return defaultMaxListeners; }, set: function(arg) { // check whether the input is a positive number (whose value is zero or // greater and not a NaN). if (typeof arg !== 'number' || arg < 0 || arg !== arg) throw new TypeError('"defaultMaxListeners" must be a positive number'); defaultMaxListeners = arg; } }); } else { EventEmitter.defaultMaxListeners = defaultMaxListeners; } // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { if (typeof n !== 'number' || n < 0 || isNaN(n)) throw new TypeError('"n" argument must be a positive number'); this._maxListeners = n; return this; }; function $getMaxListeners(that) { if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners; return that._maxListeners; } EventEmitter.prototype.getMaxListeners = function getMaxListeners() { return $getMaxListeners(this); }; // These standalone emit* functions are used to optimize calling of event // handlers for fast cases because emit() itself often has a variable number of // arguments and can be deoptimized because of that. These functions always have // the same number of arguments and thus do not get deoptimized, so the code // inside them can execute faster. function emitNone(handler, isFn, self) { if (isFn) handler.call(self); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self); } } function emitOne(handler, isFn, self, arg1) { if (isFn) handler.call(self, arg1); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1); } } function emitTwo(handler, isFn, self, arg1, arg2) { if (isFn) handler.call(self, arg1, arg2); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2); } } function emitThree(handler, isFn, self, arg1, arg2, arg3) { if (isFn) handler.call(self, arg1, arg2, arg3); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].call(self, arg1, arg2, arg3); } } function emitMany(handler, isFn, self, args) { if (isFn) handler.apply(self, args); else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) listeners[i].apply(self, args); } } EventEmitter.prototype.emit = function emit(type) { var er, handler, len, args, i, events; var doError = (type === 'error'); events = this._events; if (events) doError = (doError && events.error == null); else if (!doError) return false; // If there is no 'error' event listener then throw. if (doError) { if (arguments.length > 1) er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Unhandled "error" event. (' + er + ')'); err.context = er; throw err; } return false; } handler = events[type]; if (!handler) return false; var isFn = typeof handler === 'function'; len = arguments.length; switch (len) { // fast cases case 1: emitNone(handler, isFn, this); break; case 2: emitOne(handler, isFn, this, arguments[1]); break; case 3: emitTwo(handler, isFn, this, arguments[1], arguments[2]); break; case 4: emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); break; // slower default: args = new Array(len - 1); for (i = 1; i < len; i++) args[i - 1] = arguments[i]; emitMany(handler, isFn, this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = target._events; if (!events) { events = target._events = objectCreate(null); target._eventsCount = 0; } else { // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (events.newListener) { target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the // this._events to be assigned to a new object events = target._events; } existing = events[type]; } if (!existing) { // Optimize the case of one listener. Don't need the extra array object. existing = events[type] = listener; ++target._eventsCount; } else { if (typeof existing === 'function') { // Adding the second element, need to change to array. existing = events[type] = prepend ? [listener, existing] : [existing, listener]; } else { // If we've already got an array, just append. if (prepend) { existing.unshift(listener); } else { existing.push(listener); } } // Check for listener leak if (!existing.warned) { m = $getMaxListeners(target); if (m && m > 0 && existing.length > m) { existing.warned = true; var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' "' + String(type) + '" listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit.'); w.name = 'MaxListenersExceededWarning'; w.emitter = target; w.type = type; w.count = existing.length; if (typeof console === 'object' && console.warn) { console.warn('%s: %s', w.name, w.message); } } } } return target; } EventEmitter.prototype.addListener = function addListener(type, listener) { return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener(type, listener) { return _addListener(this, type, listener, true); }; function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; switch (arguments.length) { case 0: return this.listener.call(this.target); case 1: return this.listener.call(this.target, arguments[0]); case 2: return this.listener.call(this.target, arguments[0], arguments[1]); case 3: return this.listener.call(this.target, arguments[0], arguments[1], arguments[2]); default: var args = new Array(arguments.length); for (var i = 0; i < args.length; ++i) args[i] = arguments[i]; this.listener.apply(this.target, args); } } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = bind.call(onceWrapper, state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); this.prependListener(type, _onceWrap(this, type, listener)); return this; }; // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { var list, events, position, i, originalListener; if (typeof listener !== 'function') throw new TypeError('"listener" argument must be a function'); events = this._events; if (!events) return this; list = events[type]; if (!list) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = objectCreate(null); else { delete events[type]; if (events.removeListener) this.emit('removeListener', type, list.listener || listener); } } else if (typeof list !== 'function') { position = -1; for (i = list.length - 1; i >= 0; i--) { if (list[i] === listener || list[i].listener === listener) { originalListener = list[i].listener; position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else spliceOne(list, position); if (list.length === 1) events[type] = list[0]; if (events.removeListener) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (!events) return this; // not listening for removeListener, no need to emit if (!events.removeListener) { if (arguments.length === 0) { this._events = objectCreate(null); this._eventsCount = 0; } else if (events[type]) { if (--this._eventsCount === 0) this._events = objectCreate(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = objectKeys(events); var key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = objectCreate(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners) { // LIFO order for (i = listeners.length - 1; i >= 0; i--) { this.removeListener(type, listeners[i]); } } return this; }; function _listeners(target, type, unwrap) { var events = target._events; if (!events) return []; var evlistener = events[type]; if (!evlistener) return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); } EventEmitter.prototype.listeners = function listeners(type) { return _listeners(this, type, true); }; EventEmitter.prototype.rawListeners = function rawListeners(type) { return _listeners(this, type, false); }; EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } else { return listenerCount.call(emitter, type); } }; EventEmitter.prototype.listenerCount = listenerCount; function listenerCount(type) { var events = this._events; if (events) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; }; // About 1.5x faster than the two-arg version of Array#splice(). function spliceOne(list, index) { for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) list[i] = list[k]; list.pop(); } function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } function unwrapListeners(arr) { var ret = new Array(arr.length); for (var i = 0; i < ret.length; ++i) { ret[i] = arr[i].listener || arr[i]; } return ret; } function objectCreatePolyfill(proto) { var F = function() {}; F.prototype = proto; return new F; } function objectKeysPolyfill(obj) { var keys = []; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { keys.push(k); } return k; } function functionBindPolyfill(context) { var fn = this; return function () { return fn.apply(context, arguments); }; } },{}],2:[function(require,module,exports){ /* * Convert numbers to gematriya representation, and vice-versa. * * Licensed MIT. * * Copyright (c) 2014 Eyal Schachter * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ (function(){ var letters = {}, numbers = { '': 0, א: 1, ב: 2, ג: 3, ד: 4, ה: 5, ו: 6, ז: 7, ח: 8, ט: 9, י: 10, כ: 20, ל: 30, מ: 40, נ: 50, ס: 60, ע: 70, פ: 80, צ: 90, ק: 100, ר: 200, ש: 300, ת: 400, תק: 500, תר: 600, תש: 700, תת: 800, תתק: 900, תתר: 1000 }, i; for (i in numbers) { letters[numbers[i]] = i; } function gematriya(num, limit) { if (typeof num !== 'number' && typeof num !== 'string') { throw new TypeError('non-number or string given to gematriya()'); } var str = typeof num === 'string'; if (str) { num = num.replace(/('|")/g,''); } num = num.toString().split('').reverse(); if (!str && limit) { num = num.slice(0, limit); } num = num.map(function g(n,i){ if (str) { return limit && numbers[n] < numbers[num[i - 1]] && numbers[n] < 100 ? numbers[n] * 1000 : numbers[n]; } else { if (parseInt(n, 10) * Math.pow(10, i) > 1000) { return g(n, i-3); } return letters[parseInt(n, 10) * Math.pow(10, i)]; } }); if (str) { return num.reduce(function(o,t){ return o + t; }, 0); } else { num = num.reverse().join('').replace(/יה/g,'טו').replace(/יו/g,'טז').split(''); if (num.length === 1) { num.push("'"); } else if (num.length > 1) { num.splice(-1, 0, '"'); } return num.join(''); } } if (typeof module !== 'undefined') { module.exports = gematriya; } else { window.gematriya = gematriya; } })(); },{}],3:[function(require,module,exports){ /* (c) 2011-2015, Vladimir Agafonkin SunCalc is a JavaScript library for calculating sun/moon position and light phases. https://github.com/mourner/suncalc */ (function () { 'use strict'; // shortcuts for easier to read formulas var PI = Math.PI, sin = Math.sin, cos = Math.cos, tan = Math.tan, asin = Math.asin, atan = Math.atan2, acos = Math.acos, rad = PI / 180; // sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas // date/time constants and conversions var dayMs = 1000 * 60 * 60 * 24, J1970 = 2440588, J2000 = 2451545; function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } function toDays(date) { return toJulian(date) - J2000; } // general calculations for position var e = rad * 23.4397; // obliquity of the Earth function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } function astroRefraction(h) { if (h < 0) // the following formula works for positive altitudes only. h = 0; // if h = -0.08901179 a div/0 would occur. // formula 16.4 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. // 1.02 / tan(h + 10.26 / (h + 5.10)) h in degrees, result in arc minutes -> converted to rad: return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); } // general sun calculations function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } function eclipticLongitude(M) { var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center P = rad * 102.9372; // perihelion of the Earth return M + C + P + PI; } function sunCoords(d) { var M = solarMeanAnomaly(d), L = eclipticLongitude(M); return { dec: declination(L, 0), ra: rightAscension(L, 0) }; } var SunCalc = {}; // calculates sun position for a given date and latitude/longitude SunCalc.getPosition = function (date, lat, lng) { var lw = rad * -lng, phi = rad * lat, d = toDays(date), c = sunCoords(d), H = siderealTime(d, lw) - c.ra; return { azimuth: azimuth(H, phi, c.dec), altitude: altitude(H, phi, c.dec) }; }; // sun times configuration (angle, morning name, evening name) var times = SunCalc.times = [ [-0.833, 'sunrise', 'sunset' ], [ -0.3, 'sunriseEnd', 'sunsetStart' ], [ -6, 'dawn', 'dusk' ], [ -12, 'nauticalDawn', 'nauticalDusk'], [ -18, 'nightEnd', 'night' ], [ 6, 'goldenHourEnd', 'goldenHour' ] ]; // adds a custom time to the times config SunCalc.addTime = function (angle, riseName, setName) { times.push([angle, riseName, setName]); }; // calculations for sun times var J0 = 0.0009; function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } // returns set time for the given sun altitude function getSetJ(h, lw, phi, dec, n, M, L) { var w = hourAngle(h, phi, dec), a = approxTransit(w, lw, n); return solarTransitJ(a, M, L); } // calculates sun times for a given date and latitude/longitude SunCalc.getTimes = function (date, lat, lng) { var lw = rad * -lng, phi = rad * lat, d = toDays(date), n = julianCycle(d, lw), ds = approxTransit(0, lw, n), M = solarMeanAnomaly(ds), L = eclipticLongitude(M), dec = declination(L, 0), Jnoon = solarTransitJ(ds, M, L), i, len, time, Jset, Jrise; var result = { solarNoon: fromJulian(Jnoon), nadir: fromJulian(Jnoon - 0.5) }; for (i = 0, len = times.length; i < len; i += 1) { time = times[i]; Jset = getSetJ(time[0] * rad, lw, phi, dec, n, M, L); Jrise = Jnoon - (Jset - Jnoon); result[time[1]] = fromJulian(Jrise); result[time[2]] = fromJulian(Jset); } return result; }; // moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas function moonCoords(d) { // geocentric ecliptic coordinates of the moon var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude M = rad * (134.963 + 13.064993 * d), // mean anomaly F = rad * (93.272 + 13.229350 * d), // mean distance l = L + rad * 6.289 * sin(M), // longitude b = rad * 5.128 * sin(F), // latitude dt = 385001 - 20905 * cos(M); // distance to the moon in km return { ra: rightAscension(l, b), dec: declination(l, b), dist: dt }; } SunCalc.getMoonPosition = function (date, lat, lng) { var lw = rad * -lng, phi = rad * lat, d = toDays(date), c = moonCoords(d), H = siderealTime(d, lw) - c.ra, h = altitude(H, phi, c.dec), // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); h = h + astroRefraction(h); // altitude correction for refraction return { azimuth: azimuth(H, phi, c.dec), altitude: h, distance: c.dist, parallacticAngle: pa }; }; // calculations for illumination parameters of the moon, // based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and // Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. SunCalc.getMoonIllumination = function (date) { var d = toDays(date || new Date()), s = sunCoords(d), m = moonCoords(d), sdist = 149598000, // distance from Earth to Sun in km phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); return { fraction: (1 + cos(inc)) / 2, phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, angle: angle }; }; function hoursLater(date, h) { return new Date(date.valueOf() + h * dayMs / 24); } // calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { var t = new Date(date); if (inUTC) t.setUTCHours(0, 0, 0, 0); else t.setHours(0, 0, 0, 0); var hc = 0.133 * rad, h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) for (var i = 1; i <= 24; i += 2) { h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; a = (h0 + h2) / 2 - h1; b = (h2 - h0) / 2; xe = -b / (2 * a); ye = (a * xe + b) * xe + h1; d = b * b - 4 * a * h1; roots = 0; if (d >= 0) { dx = Math.sqrt(d) / (Math.abs(a) * 2); x1 = xe - dx; x2 = xe + dx; if (Math.abs(x1) <= 1) roots++; if (Math.abs(x2) <= 1) roots++; if (x1 < -1) x1 = x2; } if (roots === 1) { if (h0 < 0) rise = i + x1; else set = i + x1; } else if (roots === 2) { rise = i + (ye < 0 ? x2 : x1); set = i + (ye < 0 ? x1 : x2); } if (rise && set) break; h0 = h2; } var result = {}; if (rise) result.rise = hoursLater(t, rise); if (set) result.set = hoursLater(t, set); if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; return result; }; // export as Node module / AMD module / browser variable if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; else if (typeof define === 'function' && define.amd) define(SunCalc); else window.SunCalc = SunCalc; }()); },{}],4:[function(require,module,exports){ /* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant contributions as a result of maintaining hebcal.com. The JavaScript code was completely rewritten in 2014 by Eyal Schachter. */ // name, lat, long, Israel var cities = { "Ashdod": [ 31.8, 34.633, true ], "Atlanta": [ 33.75, -84.383, false ], "Austin": [ 30.266, -97.75, false ], "Baghdad": [ 33.233, 44.366, false ], "Beer Sheva": [ 31.25, 34.783, true ], "Berlin": [ 52.516, 13.4, false ], "Baltimore": [ 39.283, -76.6, false ], "Bogota": [ 4.6, -74.083, false ], "Boston": [ 42.333, -71.066, false ], "Buenos Aires": [ -34.616, -58.4, false ], "Buffalo": [ 42.883, -78.866, false ], "Chicago": [ 41.833, -87.75, false ], "Cincinnati": [ 39.1, -84.516, false ], "Cleveland": [ 41.5, -81.683, false ], "Dallas": [ 32.783, -96.8, false ], "Denver": [ 39.733, -104.983, false ], "Detroit": [ 42.333, -83.033, false ], "Eilat": [ 29.55, 34.95, true ], "Gibraltar": [ 36.133, -5.35, false ], "Haifa": [ 32.816, 34.983, true ], "Hawaii": [ 19.5, -155.5, false ], "Houston": [ 29.766, -95.366, false ], "Jerusalem": [ 31.783, 35.233, true ], "Johannesburg": [ -26.166, 28.033, false ], "Kiev": [ 50.466, 30.483, false ], "La Paz": [ -16.5, -68.15, false ], "Livingston": [ 40.283, -74.3, false ], "London": [ 51.5, -0.166, false ], "Los Angeles": [ 34.066, -118.25, false ], "Miami": [ 25.766, -80.2, false ], "Melbourne": [ -37.866, 145.133, false ], "Mexico City": [ 19.4, -99.15, false ], "Montreal": [ 45.5, -73.6, false ], "Moscow": [ 55.75, 37.7, false ], "New York": [ 40.716, -74.016, false ], "Omaha": [ 41.266, -95.933, false ], "Ottawa": [ 45.7, -76.183, false ], "Panama City": [ 8.966, -79.533, false ], "Paris": [ 48.866, 2.333, false ], "Petach Tikvah": [ 32.083, 34.883, true ], "Philadelphia": [ 39.95, -75.166, false ], "Phoenix": [ 33.45, -112.066, false ], "Pittsburgh": [ 40.433, -80, false ], "Saint Louis": [ 38.633, -90.2, false ], "Saint Petersburg": [ 59.883, 30.25, false ], "San Francisco": [ 37.783, -122.416, false ], "Seattle": [ 47.6, -122.333, false ], "Sydney": [ -33.916, 151.283, false ], "Tel Aviv": [ 32.083, 34.766, true ], "Tiberias": [ 32.966, 35.533, true ], "Toronto": [ 43.633, -79.4, false ], "Vancouver": [ 49.266, -123.116, false ], "White Plains": [ 41.033, -73.75, false ], "Washington DC": [ 38.916, -77, false ] }; function getCity(city) { city = city.split(/\s+/).map(function(w,i,c){ if (c.join(' ').toLowerCase() === 'washington dc' && i === 1) { // special case return w.toUpperCase(); } return w[0].toUpperCase() + w.slice(1).toLowerCase(); }).join(' '); return cities[city] || [ 0, 0, false ]; } exports.getCity = getCity; function listCities() { return Object.keys(cities); } exports.listCities = listCities; exports.addCity = function(city, info) { if (!Array.isArray(info)) { throw new TypeError('adding non-array city'); } if (info.length == 5) { var i = info.slice(); info = []; info[0] = (i[0] * 60 + i[1]) / 60; info[1] = (i[2] * 60 + i[3]) / 60; info[2] = i[4]; } if (info.length != 3) { throw new TypeError('length of city array is not 3'); } city = city.split(/\s+/).map(function(w){return w[0].toUpperCase() + w.slice(1).toLowerCase()}).join(' '); cities[city] = info; }; exports.nearest = function(lat, lon) { if (Array.isArray(lat)) { lat = (lat[0] * 60 + lat[1]) / 60; } if (Array.isArray(lon)) { lon = (lon[0] * 60 + lon[1]) / 60; } if (typeof lat != 'number') { throw new TypeError('incorrect lat type passed to nearest()'); } if (typeof lon != 'number') { throw new TypeError('incorrect long type passed to nearest()'); } return listCities().map(function(city){ var i = getCity(city); return { name: city, dist: Math.sqrt( Math.pow(Math.abs(i[0] - lat), 2) + Math.pow(Math.abs(i[1] - lon), 2) ) }; }).reduce(function(close,city){ return close.dist < city.dist ? close : city; }).name; }; },{}],5:[function(require,module,exports){ /* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant contributions as a result of maintaining hebcal.com. The JavaScript code was completely rewritten in 2014 by Eyal Schachter */ window.Hebcal = require('..'); var finished = false, warn = (typeof console != 'undefined' && (console.warn || console.log)) || function(){}; Hebcal.events.on('newListener', function(e){ if (e === 'ready' && !finished && Hebcal.ready) { ready(); } }); Object.defineProperty(Hebcal, 'onready', { configurable: true, get: function() { warn('Getting deprecated property Hebcal.onready'); return Hebcal.events.listeners('ready')[0]; }, set: function(func) { warn('Setting deprecated property Hebcal.onready; use Hebcal.events.on(\'ready\', func) instead'); Hebcal.events.on('ready', func); } }); if (navigator.geolocation) { Hebcal.ready = false; navigator.geolocation.getCurrentPosition(function(p){ Hebcal.defaultLocation = [p.coords.latitude,p.coords.longitude]; ready(); }, ready); } else { ready(); } function ready() { Hebcal.ready = true; finished = Hebcal.events.emit('ready'); } },{"..":10}],6:[function(require,module,exports){ /* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant contributions as a result of maintaining hebcal.com. The JavaScript code was completely rewritten in 2014 by Eyal Schachter. */ var gematriya = require('gematriya'); var charCodeAt = 'charCodeAt'; var months = exports.months = { NISAN : 1, IYYAR : 2, SIVAN : 3, TAMUZ : 4, AV : 5, ELUL : 6, TISHREI : 7, CHESHVAN: 8, KISLEV : 9, TEVET : 10, SHVAT : 11, ADAR_I : 12, ADAR_II : 13 }; var monthNames = [ ["", 0, ""], ["Nisan", 0, "ניסן"], ["Iyyar", 0, "אייר"], ["Sivan", 0, "סיון"], ["Tamuz", 0, "תמוז"], ["Av", 0, "אב"], ["Elul", 0, "אלול"], ["Tishrei", 0, "תשרי"], ["Cheshvan", 0, "חשון"], ["Kislev", 0, "כסלו"], ["Tevet", 0, "טבת"], ["Sh'vat", 0, "שבט"] ]; exports.monthNames = [ monthNames.concat([["Adar", 0, "אדר"],["Nisan", 0, "ניסן"]]), monthNames.concat([["Adar 1", 0, "אדר א'"],["Adar 2", 0, "אדר ב'"],["Nisan", 0, "ניסן"]]) ]; exports.days = { SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6 }; exports.LANG = function(str, opts){ return opts == 'h' && str[2] || (opts == 'a' && str[1] || str[0]); }; function LEAP(x) { return (1 + x * 7) % 19 < 7; } exports.LEAP = LEAP; exports.MONTH_CNT = function(x) { return 12 + LEAP(x); // boolean is cast to 1 or 0 }; exports.daysInMonth = function(month, year) { return 30 - (month == months.IYYAR || month == months.TAMUZ || month == months.ELUL || month == months.TEVET || month == months.ADAR_II || (month == months.ADAR_I && !LEAP(year)) || (month == months.CHESHVAN && !lngChesh(year)) || (month == months.KISLEV && shrtKis(year))); }; exports.monthNum = function(month) { return typeof month === 'number' ? month : month[charCodeAt](0) >= 1488 && month[charCodeAt](0) <= 1514 && /('|")/.test(month) ? gematriya(month) : month[charCodeAt](0) >= 48 && month[charCodeAt](0) <= 57 /* number */ ? parseInt(month, 10) : monthFromName(month); }; exports.dayYearNum = function(str) { return typeof str === 'number' ? str : str[charCodeAt](0) >= 1488 && str[charCodeAt](0) <= 1514 ? gematriya(str, true) : parseInt(str, 10); }; /* Days from sunday prior to start of Hebrew calendar to mean conjunction of Tishrei in Hebrew YEAR */ function hebElapsedDays(hYear){ // borrowed from original JS var m_elapsed = 235 * Math.floor((hYear - 1) / 19) + 12 * ((hYear - 1) % 19) + Math.floor(((((hYear - 1) % 19) * 7) + 1) / 19); var p_elapsed = 204 + (793 * (m_elapsed % 1080)); var h_elapsed = 5 + (12 * m_elapsed) + 793 * Math.floor(m_elapsed / 1080) + Math.floor(p_elapsed / 1080); var parts = (p_elapsed % 1080) + 1080 * (h_elapsed % 24); var day = 1 + 29 * m_elapsed + Math.floor(h_elapsed / 24); var alt_day = day + ((parts >= 19440) || ((2 == (day % 7)) && (parts >= 9924) && !(LEAP (hYear))) || ((1 == (day % 7)) && (parts >= 16789) && LEAP (hYear - 1))); return alt_day + ((alt_day % 7) === 0 || (alt_day % 7) == 3 || (alt_day % 7) == 5); } exports.hebElapsedDays = hebElapsedDays; /* Number of days in the hebrew YEAR */ function daysInYear(year) { return hebElapsedDays(year + 1) - hebElapsedDays(year); } exports.daysInYear = daysInYear; /* true if Cheshvan is long in Hebrew YEAR */ function lngChesh(year) { return (daysInYear(year) % 10) == 5; } exports.lngChesh = lngChesh; /* true if Kislev is short in Hebrew YEAR */ function shrtKis(year) { return (daysInYear(year) % 10) == 3; } exports.shrtKis = shrtKis; function monthFromName(c) { /* the Hebrew months are unique to their second letter N Nisan (November?) I Iyyar E Elul C Cheshvan K Kislev 1 1Adar 2 2Adar Si Sh Sivan, Shvat Ta Ti Te Tamuz, Tishrei, Tevet Av Ad Av, Adar אב אד אי אל אב אדר אייר אלול ח חשון ט טבת כ כסלו נ ניסן ס סיון ש שבט תמ תש תמוז תשרי */ switch (c.toLowerCase()[0]) { case 'n': case 'נ': return (c.toLowerCase()[1] == 'o') ? /* this catches "november" */ 0 : months.NISAN; case 'i': return months.IYYAR; case 'e': return months.ELUL; case 'c': case 'ח': return months.CHESHVAN; case 'k': case 'כ': return months.KISLEV; case 's': switch (c.toLowerCase()[1]) { case 'i': return months.SIVAN; case 'h': return months.SHVAT; default: return 0; } case 't': switch (c.toLowerCase()[1]) { case 'a': return months.TAMUZ; case 'i': return months.TISHREI; case 'e': return months.TEVET; } break; case 'a': switch (c.toLowerCase()[1]) { case 'v': return months.AV; case 'd': if (/(1|[^i]i|a|א)$/i.test(c)) { return months.ADAR_I; } return months.ADAR_II; // else assume sheini } break; case 'ס': return months.SIVAN; case 'ט': return months.TEVET; case 'ש': return months.SHVAT; case 'א': switch (c.toLowerCase()[1]) { case 'ב': return months.AV; case 'ד': if (/(1|[^i]i|a|א)$/i.test(c)) { return months.ADAR_I; } return months.ADAR_II; // else assume sheini case 'י': return months.IYYAR; case 'ל': return months.ELUL; } break; case 'ת': switch (c.toLowerCase()[1]) { case 'מ': return months.TAMUZ; case 'ש': return months.TISHREI; } break; } return 0; }; exports.monthFromName = monthFromName; /* Note: Applying this function to d+6 gives us the DAYNAME on or after an * absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to * absolute date d, applying it to d-1 gives the DAYNAME previous to absolute * date d, and applying it to d+7 gives the DAYNAME following absolute date d. **/ exports.dayOnOrBefore = function(day_of_week, absdate) { return absdate - ((absdate - day_of_week) % 7); }; exports.map = function(self, fun, thisp) { // originally written for http://github.com/Scimonster/localbrowse if (self === null || typeof fun != 'function') { throw new TypeError(); } var t = Object(self); var res = {}; for (var i in t) { if (t.hasOwnProperty(i)) { res[i] = fun.call(thisp, t[i], i, t); } } if (Array.isArray(self) || typeof self == 'string') { // came as an array, return an array var arr = []; for (i in res) { arr[Number(i)] = res[i]; } res = filter(arr, true); // for...in isn't guaranteed to give any meaningful order if (typeof self == 'string') { res = res.join(''); } } return res; }; function filter(self, fun, thisp) { if (self === null) { throw new TypeError('self is null'); } switch (typeof fun) { case 'function': break; // do nothing case 'string': case 'number': return self[fun]; // str/num is just the property case 'boolean': // boolean shortcuts to filter only truthy/falsy values if (fun) { fun = function (v) { return v; }; } else { fun = function (v) { return !v; }; } break; case 'object': var funOrig = fun; // save it if (fun instanceof RegExp) { // test the val against the regex fun = function (v) { return funOrig.test(v); }; break; } else if (Array.isArray(fun)) { // keep these keys fun = function (v, k) { return funOrig.indexOf(k) > -1; }; break; } default: throw new TypeError('fun is not a supported type'); } var res = {}; var t = Object(self); for (var i in t) { if (t.hasOwnProperty(i)) { var val = t[i]; // in case fun mutates it if (fun.call(thisp, val, i, t)) { // define property on res in the same manner as it was originally defined var props = Object.getOwnPropertyDescriptor(t, i); props.value = val; Object.defineProperty(res, i, props); } } } if (Array.isArray(self) || typeof self == 'string') { // came as an array, return an array var arr = []; for (i in res) { arr[Number(i)] = res[i]; } res = arr.filter(function (v) { return v; }); // for...in isn't guaranteed to give any meaningful order // can't use c.filter(arr,true) here because that would infitely recurse if (typeof self == 'string') { res = res.join(''); } } return res; } exports.filter = filter; exports.range = function(start, end, step) { step = step || 1; if (step < 0) { step = 0 - step; } var arr = [], i = start; if (start < end) { for (; i <= end; i += step) { arr.push(i); } } else { for (; i >= end; i -= step) { arr.push(i); } } return arr; }; },{"gematriya":2}],7:[function(require,module,exports){ /* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant contributions as a result of maintaining hebcal.com. The JavaScript code was completely rewritten in 2014 by Eyal Schachter. */ var c = require('./common'), greg = require('./greg'), gematriya = require('gematriya'); var shas = [ // sname, aname, hname, blatt [ "Berachot", "Berachos", "ברכות", 64 ], [ "Shabbat", "Shabbos", "שבת", 157 ], [ "Eruvin", "Eruvin", "עירובין", 105 ], [ "Pesachim", 0, "פסחים", 121 ], [ "Shekalim", 0, "שקלים", 22 ], [ "Yoma", 0, "יומא", 88 ], [ "Sukkah", 0, "סוכה", 56 ], [ "Beitzah", 0, "ביצה", 40 ], [ "Rosh Hashana", 0, "ראש השנה", 35 ], [ "Taanit", "Taanis", "תענית", 31 ], [ "Megillah", 0, "מגילה", 32 ], [ "Moed Katan", 0, "מועד קטן", 29 ], [ "Chagigah", 0, "חגיגה", 27 ], [ "Yevamot", "Yevamos", "יבמות", 122 ], [ "Ketubot", "Kesubos", "כתובות", 112 ], [ "Nedarim", 0, "נדרים", 91 ], [ "Nazir", 0, "נזיר", 66 ], [ "Sotah", 0, "סוטה", 49 ], [ "Gitin", 0, "גיטין", 90 ], [ "Kiddushin", 0, "קידושין", 82 ], [ "Baba Kamma", 0, "בבא קמא", 119 ], [ "Baba Metzia", 0, "בבא מציעא", 119 ], [ "Baba Batra", "Baba Basra", "בבא בתרא", 176 ], [ "Sanhedrin", 0, "סנהדרין", 113 ], [ "Makkot", "Makkos", "מכות", 24 ], [ "Shevuot", "Shevuos", "שבועות", 49 ], [ "Avodah Zarah", 0, "עבודה זרה", 76 ], [ "Horayot", "Horayos", "הוריות", 14 ], [ "Zevachim", 0, "זבחים", 120 ], [ "Menachot", "Menachos", "מנחות", 110 ], [ "Chullin", 0, "חולין", 142 ], [ "Bechorot", "Bechoros", "בכורות", 61 ], [ "Arachin", 0, "ערכין", 34 ], [ "Temurah", 0, "תמורה", 34 ], [ "Keritot", "Kerisos", "כריתות", 28 ], [ "Meilah", 0, "מעילה", 22 ], [ "Kinnim", 0, "קנים", 4 ], [ "Tamid", 0, "תמיד", 10 ], [ "Midot", "Midos", "מדות", 4 ], [ "Niddah", 0, "נדה", 73 ] ].map(function(m){ return {name: m.slice(0,3), blatt: m[3]}; }); exports.dafyomi = function(gregdate) { var dafcnt = 40, cno, dno, osday, nsday, total, count, j, cday, blatt; if (!(gregdate instanceof Date)) { throw new TypeError('non-date given to dafyomi'); } osday = greg.greg2abs(new Date(1923, 8, 11)); nsday = greg.greg2abs(new Date(1975, 5, 24)); cday = greg.greg2abs(gregdate); if (cday < osday) { // no cycle; dy didn't start yet return {name: [], blatt: 0}; } if (cday >= nsday) { // "new" cycle cno = 8 + ( (cday - nsday) / 2711 ); dno = (cday - nsday) % 2711; } else { // old cycle cno = 1 + ( (cday - osday) / 2702 ); dno = (cday - osday) % 2702; } // Find the daf taking note that the cycle changed slightly after cycle 7. total = blatt = 0; count = -1; // Fix Shekalim for old cycles if (cno <= 7) { shas[4].blatt = 13; } else { shas[4].blatt = 22; } // Find the daf j = 0; while (j < dafcnt) { count++; total = total + shas[j].blatt - 1; if (dno < total) { blatt = (shas[j].blatt + 1) - (total - dno); // fiddle with the weird ones near the end switch (count) { case 36: blatt = blatt + 21; break; case 37: blatt = blatt + 24; break; case 38: blatt = blatt + 33; break; default: break; } // Bailout j = 1 + dafcnt; } j++; } return {name: shas[count].name, blatt: blatt}; }; exports.dafname = function(daf, o) { return c.LANG(daf.name, o) + ' ' + (o === 'h' ? gematriya(daf.blatt) : daf.blatt); }; },{"./common":6,"./greg":8,"gematriya":2}],8:[function(require,module,exports){ /* Hebcal - A Jewish Calendar Generator Copyright (C) 1994-2004 Danny Sadinoff Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved. https://github.com/hebcal/hebcal-js This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Danny Sadinoff can be reached at danny@sadinoff.com Michael Radwin has made significant con