hebcal 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ jquery.js
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Isaac Betesh
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ # HebCal
2
+
3
+ Determines the date of Passover for a Gregorian year. Also includes boolean functions to check whether a date is a Jewish holiday, Fast Day or Rosh Chodesh.
4
+ Supported languages:
5
+ Javascript
6
+ Ruby
7
+
8
+ ## Installation as a Ruby gem
9
+
10
+ Add this line to your application's Gemfile:
11
+ gem 'hebcal'
12
+ And then execute:
13
+ $ bundle
14
+ Or install it yourself as:
15
+ $ gem install hebcal
16
+
17
+ ## General notes
18
+
19
+ 1. 3- and 4-digit years are supported, so the domain of valid years is 100-9999. For years before the Gregorian transition (1582), the transition is ignored and the proleptic Gregorian calendar is used.
20
+
21
+ ## Ruby Version
22
+
23
+ ### To Run Unit Tests
24
+ $ rake test
25
+
26
+ ### To Use
27
+
28
+ #### Calculating the date of Passover
29
+ 1. At the top of the file where the class is defined, declare `require `hebcal``
30
+
31
+ 1. In the class, declare `include HebCal::Passover`
32
+
33
+ 1. `WhenIsPesach(yyyy)` returns a Ruby Time object representing midnight on the first day of passover, where `yyyy` is the Gregorian year
34
+
35
+ Note that the date returned is the first day of Pesach, not the day on which Pesach begins at sunset.
36
+
37
+ #### Finding out if a date is a holiday
38
+ 1. At the top of the file where the class is defined, declare `require `hebcal``
39
+
40
+ 1. In the desired class, declare `include HebCal::Holidays`
41
+
42
+ 1. `IsPesach(d)` returns true iff d is a Ruby Time object representing a date during Pesach. Note that the day on which Pesach begins at sunset returns false.
43
+ 1. The following functions work in a similar way to `IsPesach()`:
44
+ 1. `IsShavuot()`, `IsRoshHashanah()`, `IsYomKippur()`, `IsSukkot()`
45
+
46
+ 1. `IsRegel()`: `IsPesach() || IsShavuot || IsSukkot()`
47
+
48
+ 1. `IsMoed()`: Hol HaMoed Pesach or Hol HaMoed Sukkot
49
+
50
+ 1. `IsYomTov()`: `IsPesach() || IsShavuot() || IsRoshHashanah() || IsSukkot()) && !IsMoed()`
51
+
52
+ Note that IsYomTov(yk) == false, where yk is the date of Yom Kippur.
53
+
54
+ 1. `IsPurim()`, `IsHanuka()`
55
+
56
+ 1. `Is10Tevet()`, `IsTaanitEster()`, `Is17Tamuz()`, `Is9Av()`, `IsFastOfGedalia()`
57
+
58
+ 1. `IsTaanit()`: `Is10Tevet() || IsTaanitEster() || Is17Tamuz() || Is9Av() || IsFastOfGedalia()`
59
+
60
+ 1. `IsRoshChodesh()`
61
+
62
+ ## Javascript Version
63
+
64
+ ### To Run Unit Tests
65
+ 1. Open index.html in a browser. You should see a lot of green text saying that tests passed. If not, javascript may not be enabled in your browser. Scroll down to the bottom and verify that the summary says all tests passed.
66
+
67
+ ### To Use
68
+ 1. Include the javascript source file in your HTML page
69
+
70
+ 1. If using Ruby On Rails, you can declare `//= require hebcal` at the top of a javascript or coffeescript file
71
+ 1. To include the script explicitly in an html file,
72
+
73
+ `<script src="app/assets/javascripts/hebcal/passover.js" type="text/javascript"></script>`
74
+
75
+ 1. All date formats are YYYY-mm-dd, where month is index from 1 (i.e. 1 == January, not the usual javascript index of 0 == January!) and YYYY is the Gregorian year.
76
+
77
+ 1. $.whenIsPesach(yyyy) returns a date in the above format, where yyyy is the Gregorian year.
78
+
79
+ Note that the date returned is the first day of Pesach, not the day on which Pesach begins at sunset.
80
+ 1. $.isPesach(d) returns true iff d is a date during Pesach, in the above format. Note that the day on which Pesach begins at sunset returns false.
81
+ 1. The following functions work in a similar way to $.isPesach():
82
+ 1. $.isShavuot(), $.isRoshHashanah(), $.isYomKippur(), $.isSukkot();
83
+
84
+ 1. $.isRegel(): $.isPesach() || $.isShavuot() || $.isSukkot();
85
+
86
+ 1. $.isMoed(): Hol HaMoed Pesach or Hol HaMoed Sukkot;
87
+
88
+ 1. $.isYomTov(): ($.isPesach() || $.isSukkot() || $.isShavuot() || $.isRoshHashanah()) && !$.isMoed();
89
+
90
+ Note that isYomTov(yk) == false, where yk is the date of Yom Kippur.
91
+
92
+ 1. `$.isPurim()`, `$.isHanuka()`
93
+
94
+ 1. `$.isRoshChodesh()`
95
+
96
+ 1. `$.is10Tevet()`, `$.isTaanitEster()`, `$.is17Tamuz()`, `$.is9Av()`, `$.isFastOfGedalia()`
97
+
98
+ 1. `$.isTaanit()`: `$.is10Tevet() || $.isTaanitEster() || $.is17Tamuz() || $.is9Av() || $.isFastOfGedalia()`
99
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new
7
+
8
+ task :default => :spec
9
+ task :test => :spec
10
+
@@ -0,0 +1 @@
1
+ //= require ./passover
@@ -0,0 +1,253 @@
1
+ (function($) {
2
+
3
+ var SHAVUOT_DISTANCE = 50;
4
+ var SUKKOT_DISTANCE = 59 * 3;
5
+ var PURIM_DISTANCE = -30;
6
+ var STANDARD_HANUKAH_DISTANCE = 59 * 4 + 10;
7
+ var FAST_AB_DISTANCE = 59 * 2 - 6;
8
+ var STANDARD_10_TEVET_DISTANCE = 59 * 4 + 30 - 5;
9
+
10
+ function is_leap_year(year) {
11
+ return (-1 != [3,6,8,11,14,17,19].indexOf(year % 19));
12
+ }
13
+
14
+ function precedes_leap_year(year) {
15
+ return is_leap_year(year+1);
16
+ }
17
+
18
+ function leadingZero(n) {
19
+ return n <= 9 ? "0" + n : n;
20
+ }
21
+
22
+ function formatDate(date) {
23
+ return date.getFullYear() + "-" + leadingZero(date.getMonth()+1) + "-" + leadingZero(date.getDate());
24
+ }
25
+
26
+ function calculate_pesach(yearG) {
27
+
28
+ // CONSTANTS
29
+ var HALAKIM_PER_HOUR = 1080;
30
+ var HALAKIM_PER_DAY = 24 * HALAKIM_PER_HOUR;
31
+ var ANNUAL_DRIFT = 10 * HALAKIM_PER_DAY + 21 * HALAKIM_PER_HOUR + 204;
32
+ var JULIAN_ANNUAL_CALENDAR_DRIFT = HALAKIM_PER_HOUR * 6;
33
+ var JULIAN_YEAR = 365.25 * HALAKIM_PER_DAY;
34
+
35
+ var LUNAR_CYCLE = 29 * HALAKIM_PER_DAY + 12 * HALAKIM_PER_HOUR + 793;
36
+ var HALAKIM_PER_19_YEAR_CYCLE = 235 * LUNAR_CYCLE;
37
+
38
+ var JULIAN_ERROR_PER_19_YEAR_CYCLE = JULIAN_YEAR * 19 - HALAKIM_PER_19_YEAR_CYCLE;
39
+ var EPOCH_TEKUFAH = -(20 * HALAKIM_PER_HOUR + 302);
40
+
41
+ var MOLAD_ZAQEN = 6 * HALAKIM_PER_HOUR;
42
+ var TUTAKPAT = 15 * HALAKIM_PER_HOUR + 589;
43
+ var TARAD = 9 * HALAKIM_PER_HOUR + 204;
44
+
45
+ // CALCULATE MOLAD
46
+ var yearH = yearG + 3760;
47
+ var drift_since_epoch = (LUNAR_CYCLE + EPOCH_TEKUFAH + (LUNAR_CYCLE - ANNUAL_DRIFT) * (yearH % 19) - HALAKIM_PER_DAY) % LUNAR_CYCLE;
48
+ var year_in_julian_cycle = yearG % 4;
49
+ var molad = LUNAR_CYCLE + HALAKIM_PER_DAY + MOLAD_ZAQEN + drift_since_epoch + (year_in_julian_cycle * JULIAN_ANNUAL_CALENDAR_DRIFT) - (JULIAN_ERROR_PER_19_YEAR_CYCLE * Math.floor(yearH / 19));
50
+ var halakim_into_day = molad % HALAKIM_PER_DAY;
51
+
52
+ // CALCULATE CALENDAR DATE OF PESACH
53
+ var gregorian_divergence = Math.floor(yearG/100) - Math.floor(yearG/400) - 2;
54
+ var pesach_julian_day = (molad - halakim_into_day) / HALAKIM_PER_DAY
55
+
56
+ var day_of_week = ((3 * yearG) + (5 * year_in_julian_cycle) + pesach_julian_day) % 7;
57
+ var pesach_day = pesach_julian_day + gregorian_divergence;
58
+
59
+ if (-1 != [1,3,5].indexOf(day_of_week)) {
60
+ pesach_day += 1;
61
+ } else if (0 == day_of_week && !precedes_leap_year(yearH) && halakim_into_day >= TARAD + MOLAD_ZAQEN) {
62
+ pesach_day += 2;
63
+ } else if (6 == day_of_week && is_leap_year(yearH) && halakim_into_day >= TUTAKPAT + MOLAD_ZAQEN) {
64
+ pesach_day += 1;
65
+ }
66
+ var pesach_month = 2;
67
+
68
+ return new Date(yearG, pesach_month, pesach_day);
69
+ }
70
+
71
+ $.whenIsPesach = function(yearG) {
72
+ return formatDate(calculate_pesach(yearG));
73
+ };
74
+
75
+ function parse_date(date) {
76
+ date = /([0-9]{3,5})-([0-9]{2})-([0-9]{2})/.exec(date);
77
+ return new Date(date[1], date[2] - 1, date[3]);
78
+ }
79
+
80
+ function get_distance(date1, date2) {
81
+ hours = (date2 - date1) / 60 / 60 / 1000;
82
+ if (-1 != [1, -23].indexOf(hours % 24)) {
83
+ hours -= 1;
84
+ } else if (-1 != [-1, 23].indexOf(hours % 24)) {
85
+ hours += 1;
86
+ }
87
+ return hours / 24;
88
+ }
89
+
90
+ function pesach_distance(date) {
91
+ date = parse_date(date);
92
+ var pesach = calculate_pesach(date.getFullYear());
93
+ return get_distance(pesach, date);
94
+ }
95
+
96
+ function is_distance_in_range(distance, begin, length) {
97
+ return distance >= begin && distance <= begin + length - 1;
98
+ }
99
+
100
+ function get_pesach_and_year_length(date) {
101
+ var year = date.getFullYear();
102
+ var pesach1 = calculate_pesach(year);
103
+ var pesach2;
104
+ if (get_distance(pesach1, date) < -59) {
105
+ pesach2 = pesach1;
106
+ pesach1 = calculate_pesach(year - 1);
107
+ } else {
108
+ pesach2 = calculate_pesach(year + 1);
109
+ }
110
+ var result = {};
111
+ result.pesach = pesach1;
112
+ result.length = get_distance(pesach1, pesach2);
113
+ return result;
114
+ }
115
+
116
+ $.isPesach = function(date) {
117
+ return is_distance_in_range(pesach_distance(date), 0, 8);
118
+ };
119
+
120
+ $.isShavuot = function(date) {
121
+ return is_distance_in_range(pesach_distance(date), SHAVUOT_DISTANCE, 2);
122
+ };
123
+
124
+ $.isRoshHashanah = $.isRoshHaShanah = function(date) {
125
+ return is_distance_in_range(pesach_distance(date), SUKKOT_DISTANCE - 14, 2);
126
+ };
127
+
128
+ $.isYomKippur = function(date) {
129
+ return is_distance_in_range(pesach_distance(date), SUKKOT_DISTANCE - 5, 1);
130
+ };
131
+
132
+ $.isSukkot = function(date) {
133
+ return is_distance_in_range(pesach_distance(date), SUKKOT_DISTANCE, 9);
134
+ };
135
+
136
+ $.isMoed = function(date) {
137
+ var distance = pesach_distance(date);
138
+ return is_distance_in_range(distance, 2, 4) || is_distance_in_range(distance, SUKKOT_DISTANCE + 2, 5);
139
+ };
140
+
141
+ $.isRegel = function(date) {
142
+ var distance = pesach_distance(date);
143
+ return is_distance_in_range(distance, 0, 8) || is_distance_in_range(distance, SHAVUOT_DISTANCE, 2) || is_distance_in_range(distance, SUKKOT_DISTANCE, 9);
144
+ };
145
+
146
+ $.isYomTov = function(date) {
147
+ // Note that Yom Kippur is not a Yom Tov
148
+ var distance = pesach_distance(date);
149
+ return is_distance_in_range(distance, 0, 2) || is_distance_in_range(distance, 6, 2) || is_distance_in_range(distance, SHAVUOT_DISTANCE, 2) || is_distance_in_range(distance, SUKKOT_DISTANCE - 14, 2) || is_distance_in_range(distance, SUKKOT_DISTANCE, 2) || is_distance_in_range(distance, SUKKOT_DISTANCE + 7, 2);
150
+ };
151
+
152
+ $.isPurim = function(date) {
153
+ return is_distance_in_range(pesach_distance(date), PURIM_DISTANCE, 1);
154
+ }
155
+
156
+ $.isHanuka = $.isHanukka = $.isHanukah = $.isHanukkah = $.isChanuka = $.isChanukka = $.isChanukah = $.isChanukkah = function(date) {
157
+ date = parse_date(date);
158
+ var data = get_pesach_and_year_length(date);
159
+ var distance = STANDARD_HANUKAH_DISTANCE;
160
+ if (-1 != [355, 385].indexOf(data.length)) {
161
+ distance = distance + 1;
162
+ }
163
+ return is_distance_in_range(get_distance(data.pesach, date), distance, 8);
164
+ }
165
+
166
+ $.isRoshChodesh = $.isRoshHodesh = function(date) {
167
+ date = parse_date(date);
168
+ var result = get_pesach_and_year_length(date);
169
+ var distance = get_distance(result.pesach, date);
170
+ var length = result.length;
171
+ var distances = [ -59 + 15, -59 + 16, -59 + 30 + 15];
172
+ distances = distances.concat([ 15, 16, 30 + 15]);
173
+ distances = distances.concat([ 59 + 15, 59 + 16, 59 + 30 + 15]);
174
+ distances = distances.concat([2 * 59 + 15, 2 * 59 + 16]);
175
+ distances = distances.concat([3 * 59 + 15, 3 * 59 + 16, 3 * 59 + 30 + 15]);
176
+ if (-1 != [353, 383].indexOf(length)) {
177
+ distances = distances.concat([4 * 59 + 15]);
178
+ distances = distances.concat([4 * 59 + 30 + 14]);
179
+ if (383 == length) {
180
+ distances = distances.concat([5 * 59 + 14, 5 * 59 + 15]);
181
+ }
182
+ } else if (-1 != [354, 384].indexOf(length)) {
183
+ distances = distances.concat([4 * 59 + 15, 4 * 59 + 16]);
184
+ distances = distances.concat([4 * 59 + 30 + 15]);
185
+ if (384 == length) {
186
+ distances = distances.concat([5 * 59 + 15, 5 * 59 + 16]);
187
+ }
188
+ } else if (-1 != [355, 385].indexOf(length)) {
189
+ distances = distances.concat([3 * 59 + 30 + 16]);
190
+ distances = distances.concat([4 * 59 + 16, 4 * 59 + 17]);
191
+ distances = distances.concat([4 * 59 + 30 + 16]);
192
+ if (385 == length) {
193
+ distances = distances.concat([5 * 59 + 16, 5 * 59 + 17]);
194
+ }
195
+ }
196
+ return (-1 != distances.indexOf(distance));
197
+ }
198
+
199
+ function is_fast_with_sunday_postponement(date, distance) {
200
+ var dow = parse_date(date).getDay();
201
+ var pesach_dist = pesach_distance(date);
202
+ return (6 != dow && is_distance_in_range(pesach_dist, distance, 1)) || (0 == dow && is_distance_in_range(pesach_dist, distance + 1, 1));
203
+ }
204
+
205
+ $.is9Ab = $.is9Av = function(date) {
206
+ return is_fast_with_sunday_postponement(date, FAST_AB_DISTANCE);
207
+ }
208
+
209
+ $.is17Tamuz = $.is17Tammuz = function(date) {
210
+ return is_fast_with_sunday_postponement(date, FAST_AB_DISTANCE - 21);
211
+ }
212
+
213
+ $.isTzomGedalia = $.isTzomGedaliah = $.isFastOfGedalia = $.isFastOfGedaliah = function(date) {
214
+ return is_fast_with_sunday_postponement(date, SUKKOT_DISTANCE - 12);
215
+ }
216
+
217
+ $.isTaanitEsther = $.isTaanitEster = function(date) {
218
+ var dow = parse_date(date).getDay();
219
+ return (6 != dow && is_distance_in_range(pesach_distance(date), PURIM_DISTANCE - 1, 1)) || (4 == dow && is_distance_in_range(pesach_distance(date), PURIM_DISTANCE - 3, 1));
220
+ }
221
+
222
+ $.is10Tevet = function(date) {
223
+ date = parse_date(date);
224
+ var data = get_pesach_and_year_length(date);
225
+ var distance = STANDARD_10_TEVET_DISTANCE
226
+ if (-1 != [353, 383].indexOf(data.length)) {
227
+ distance = distance - 1;
228
+ }
229
+ if (-1 != [355, 385].indexOf(data.length)) {
230
+ distance = distance + 1;
231
+ }
232
+ return is_distance_in_range(get_distance(data.pesach, date), distance, 1);
233
+ }
234
+
235
+ $.isTaanit = function(date) {
236
+ var dow = parse_date(date).getDay();
237
+ if (6 == dow) {
238
+ return false;
239
+ }
240
+ var distance = pesach_distance(date);
241
+ if (is_distance_in_range(distance, FAST_AB_DISTANCE, 1) || is_distance_in_range(distance, FAST_AB_DISTANCE - 21, 1) || is_distance_in_range(distance, SUKKOT_DISTANCE - 12, 1) || is_distance_in_range(distance, PURIM_DISTANCE - 1, 1)) {
242
+ return true;
243
+ }
244
+ if (0 == dow && (is_distance_in_range(distance, FAST_AB_DISTANCE + 1, 1) || is_distance_in_range(distance, FAST_AB_DISTANCE - 21 + 1, 1) || is_distance_in_range(distance, SUKKOT_DISTANCE - 12 + 1, 1))) {
245
+ return true;
246
+ }
247
+ if (4 == dow && is_distance_in_range(distance, PURIM_DISTANCE - 3, 1)) {
248
+ return true;
249
+ }
250
+ return $.is10Tevet(date);
251
+ }
252
+
253
+ })($);
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/hebcal/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Isaac Betesh"]
6
+ gem.email = ["iybetesh@gmail.com"]
7
+ gem.description = `cat README.md`
8
+ gem.summary = 'Determines the date of Passover for a Gregorian year. Determines whether a Gregorian date is a Jewish holiday.'
9
+ gem.homepage = "https://github.com/betesh/hebcal"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "hebcal"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = HebCal::VERSION
17
+ gem.license = 'MIT'
18
+ end
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Aliyot</title>
5
+ <script src="test/test.js" type="text/javascript"></script>
6
+ <script src="app/assets/javascripts/hebcal/passover.js" type="text/javascript"></script>
7
+ </head>
8
+ <body onload="RunTest()">
9
+ <div id="test_results">
10
+ </div>
11
+ </body>
12
+ </html>