hebcal
Version:
An easy to use, richly-featured, perpetual Jewish Calendar API
1,712 lines (1,451 loc) • 120 kB
JavaScript
(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