hebcal-fixed
Version:
An easy to use, richly-featured, perpetual Jewish Calendar API
1,707 lines (1,435 loc) • 116 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({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.
function EventEmitter() {
this._events = this._events || {};
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.
EventEmitter.defaultMaxListeners = 10;
// 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(n) {
if (!isNumber(n) || n < 0 || isNaN(n))
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(isObject(this._events.error) && !this._events.error.length)) {
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('Uncaught, unspecified "error" event. (' + er + ')');
err.context = er;
throw err;
}
}
}
handler = this._events[type];
if (isUndefined(handler))
return false;
if (isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
}
} else if (isObject(handler)) {
args = Array.prototype.slice.call(arguments, 1);
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);
else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!isFunction(listener))
throw TypeError('listener must be a function');
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}
listeners = this._events[type];
if (isFunction(listeners)) {
this.removeListener(type, listeners);
} else if (listeners) {
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.prototype.listenerCount = function(type) {
if (this._events) {
var evlistener = this._events[type];
if (isFunction(evlistener))
return 1;
else if (evlistener)
return evlistener.length;
}
return 0;
};
EventEmitter.listenerCount = function(emitter, type) {
return emitter.listenerCount(type);
};
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isUndefined(arg) {
return arg === void 0;
}
},{}],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 contributions as a result of
maintaining hebcal.com.
The JavaScript code was completely rewritten in 2014 by Eyal Schachter.
*/
var floor = Math.floor,
t0t1 = [30, 31],
tMonthLengths = [0, 31, 28, 31].concat(t0t1, t0t1, 31, t0t1, t0t1),
monthLengths = [
tMonthLengths.slice()
];
tMonthLengths[2]++;
monthLengths.push(tMonthLengths);
exports.daysInMonth = function(month, year) { // 1 based months
return monthLengths[+LEAP(year)][month];
};
exports.monthNames = [
'',
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
exports.lookupMonthNum = function(month) {
return new Date(month + ' 1').getMonth() + 1;
};
function dayOfYear (date) {
if (!date instanceof Date) {
throw new TypeError('Argument to greg.dayOfYear not a Date');
}
var doy = date.getDate() + 31 * date.getMonth();
if (date.getMonth() > 1) { // FEB
doy -= floor((4 * (date.getMonth() + 1) + 23) / 10);
if (LEAP(date.getFullYear())) {
doy++;
}
}
return doy;
}
exports.dayOfYear = dayOfYear;
function LEAP (year) {
return !(year % 4) && ( !!(year % 100) || !(year % 400) );
}
exports.LEAP = LEAP;
exports.greg2abs = function(date) { // "absolute date"
var year = date.getFullYear() - 1;
return (dayOfYear(date) + // days this year
365 * year + // + days in prior years
( floor(year / 4) - // + Julian Leap years
floor(year / 100) + // - century years
floor(year / 400))); // + Gregorian leap years
};
/*
* See the footnote on page 384 of ``Calendrical Calculations, Part II:
* Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
* Clamen, Software--Practice and Experience, Volume 23, Number 4
* (April, 1993), pages 383-404 for an explanation.
*/
exports.abs2greg = function(theDate) {
// calculations copied from original JS code
var d0 = theDate - 1;
var n400 = floor(d0 / 146097);
var d1 = floor(d0 % 146097);
var n100 = floor(d1 / 36524);
var d2 = d1 % 36524;
var n4 = floor(d2 / 1461);
var d3 = d2 % 1461;
var n1 = floor(d3 / 365);
var day = ((d3 % 365) + 1);
var year = (400 * n400 + 100 * n100 + 4 * n4 + n1);
if (4 == n100 || 4 == n1) {
return new Date(year, 11, 31);
}
return new Date(new Date(++year, 0, day).setFullYear(year)); // new Date() is very smart
};
},{}],9:[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'),
suncalc = require('suncalc'),
cities = require('./cities'),
gematriya = require('gematriya');
suncalc.addTime(-16.1, 'alot_hashachar', 0);
suncalc.addTime(-11.5, 'misheyakir', 0);
suncalc.addTime(-10.2, 'misheyakir_machmir', 0);
suncalc.addTime(-8.5, 0, 'tzeit');
suncalc.addTime(-5.879999999999995, 0, 'tzeitstars');
// for minifying optimizations
var getFullYear = 'getFullYear',
getMonth = 'getMonth',
getDate = 'getDate',
getTime = 'getTime',
abs = 'abs',
hour = 'hour',
months = c.months,
TISHREI = months.TISHREI,
MONTH_CNT = c.MONTH_CNT,
daysInMonth = c.daysInMonth,
dayOnOrBefore = c.dayOnOrBefore,
prototype = HDate.prototype;
function HDate(day, month, year) {
var me = this;
switch (arguments.length) {
case 0:
return new HDate(new Date());
case 1:
if (typeof day == 'undefined') {
return new HDate();
} else if (day instanceof Date) {
// we were passed a Gregorian date, so convert it
var d = abs2hebrew(greg.greg2abs(day));
/*if (d.sunset() < day) {
d = d.next();
}*/
return d;
} else if (day instanceof HDate) {
var d = new HDate(day[getDate](), day[getMonth](), day[getFullYear]());
d.il = day.il;
d.setLocation(d.lat, d.long);
return d;
} else if (typeof day == 'string') {
switch (day.toLowerCase().trim()) {
case 'today':
return new HDate();
case 'yesterday':
return new HDate().prev();
case 'tomorrow':
return new HDate().next();
}
if (/\s/.test(day)) {
var s = day.split(/\s+/);
if (s.length == 2) {
return new HDate(s[0], s[1]);
} else if (s.length == 3) {
return new HDate(s[0], s[1], s[2]);
} else if (s.length == 4) { // should only be if s[1] is Adar
if (/i/i.test(s[2])) { // Using I[I] syntax
s[2] = s[2].length;
} // otherwise using 1|2 syntax
return new HDate(s[0], s[1] + s[2], s[3]);
}
}
} else if (typeof day == 'number') { // absolute date
return abs2hebrew(day);
}
throw new TypeError('HDate called with bad argument');
case 2:
return new HDate(day, month, (new HDate)[getFullYear]());
case 3:
me.day = me.month = 1;
me.year = c.dayYearNum(year);
me.setMonth(c.monthNum(month));
me.setDate(c.dayYearNum(day));
break;
default:
throw new TypeError('HDate called with bad arguments');
}
return me.setLocation.apply(me, HDate.defaultLocation);
}
HDate.defaultLocation = [0, 0];
Object.defineProperty(HDate, 'defaultCity', {
enumerable: true,
configurable: true,
g