prayer_times 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +14 -0
- data/README.md +81 -0
- data/Rakefile +11 -0
- data/lib/prayer_times/calculation.rb +236 -0
- data/lib/prayer_times/calculation_method.rb +85 -0
- data/lib/prayer_times/calculation_methods.rb +144 -0
- data/lib/prayer_times/calculator.rb +57 -0
- data/lib/prayer_times/constants.rb +51 -0
- data/lib/prayer_times/math_helpers.rb +55 -0
- data/lib/prayer_times/setters.rb +71 -0
- data/lib/prayer_times/version.rb +4 -0
- data/lib/prayer_times.rb +41 -0
- data/prayer_times.gemspec +23 -0
- data/test/lib/prayer_times/calculation_method_test.rb +57 -0
- data/test/lib/prayer_times/calculation_methods_test.rb +39 -0
- data/test/lib/prayer_times/calculation_test.rb +123 -0
- data/test/lib/prayer_times/calculator_test.rb +16 -0
- data/test/lib/prayer_times/math_helpers_test.rb +46 -0
- data/test/lib/prayer_times/prayer_times_test.rb +23 -0
- data/test/lib/prayer_times/setters_test.rb +105 -0
- data/test/lib/prayer_times/version_test.rb +9 -0
- data/test/test_helper.rb +9 -0
- metadata +106 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 88ba28e5dfcc4e57a3cb76df12221a046202ff41
|
|
4
|
+
data.tar.gz: d8d1255686349c190550f835fbd8d25e4f610344
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: eed7fbbc8d954955ad284590a9e07f1784cbf41f1296185fc036fa331e1be13976d37d8110321d5af7e93a44fa7269b275689286c8c7a2ce7e7953912be33163
|
|
7
|
+
data.tar.gz: cf76f062cb054529ce1b40daab520bf555209ae643b712cb5ec4cf701c9d5b1d34c8e3be6a110e09ec5ff314619d2368d5e044381a893abc853a121cbdcbd311
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright (c) 2013 Khaled alHabache
|
|
2
|
+
|
|
3
|
+
Original js Code: Hamid Zarrabi-Zadeh - PrayTimes.org
|
|
4
|
+
|
|
5
|
+
License: GNU LGPL v3.0
|
|
6
|
+
|
|
7
|
+
TERMS OF USE:
|
|
8
|
+
Permission is granted to use this code, with or
|
|
9
|
+
without modification, in any website or application
|
|
10
|
+
provided that credit is given to the original work
|
|
11
|
+
with a link back to PrayTimes.org.
|
|
12
|
+
|
|
13
|
+
This program is distributed in the hope that it will
|
|
14
|
+
be useful, but WITHOUT ANY WARRANTY.
|
data/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# PrayerTimes
|
|
2
|
+
|
|
3
|
+
Flexiable and configurable calculation for Muslim prayers times.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
gem 'prayer_times'
|
|
10
|
+
|
|
11
|
+
And then execute:
|
|
12
|
+
|
|
13
|
+
$ bundle
|
|
14
|
+
|
|
15
|
+
Or install it yourself as:
|
|
16
|
+
|
|
17
|
+
$ gem install prayer_times
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Baisc usage
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'prayer_times'
|
|
25
|
+
pt = PrayerTimes.new("Makkah")
|
|
26
|
+
times = pt.get_times(Date.today(), [31,36], 3)
|
|
27
|
+
puts times.inspect
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Global configuration
|
|
31
|
+
|
|
32
|
+
You can have a [global configuration](https://github.com/Startappz/prayer_times/wiki/Global-Configuration) through the PrayerTimes module:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
require 'prayer_times'
|
|
36
|
+
PrayerTimes.time_format = '12h'
|
|
37
|
+
PrayerTimes.time_suffixes = {:am => 'صباحا', :pm => 'مساءا'}
|
|
38
|
+
# and others...
|
|
39
|
+
```
|
|
40
|
+
#### Adding more methods
|
|
41
|
+
|
|
42
|
+
There are [several methods](https://github.com/Startappz/prayer_times/wiki/Calculation-Methods) that are shiped with this gem by default. You can list, add new or update existing ones.
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
PrayerTimes.calculation_methods
|
|
46
|
+
PrayerTimes.calculation_methods.names
|
|
47
|
+
PrayerTimes.calculation_methods.add("Test", "Testing method", fajr: 16.5, asr: 'Hanafi', isha: '80 min')
|
|
48
|
+
new_method = PrayerTimes.calculation_methods["Test"]
|
|
49
|
+
new_method.description = "new description"
|
|
50
|
+
new_method.settings = {fajr: 19.5, isha: '33 min'}
|
|
51
|
+
PrayerTimes.calculation_methods.delete("Test")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Instance configuration
|
|
55
|
+
|
|
56
|
+
As with the global configuration, you can [set](https://github.com/Startappz/prayer_times/wiki/Instance-Configuration) the configuration on the object level:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
require 'prayer_times'
|
|
60
|
+
PrayerTimes.time_format = '12h'
|
|
61
|
+
PrayerTimes.time_suffixes = {am: 'صباحا', pm: 'مساءا'}
|
|
62
|
+
options = {
|
|
63
|
+
time_format: '12h',
|
|
64
|
+
time_suffixes: {am: => 'صباحا', pm: 'مساءا'}
|
|
65
|
+
# and others...
|
|
66
|
+
}
|
|
67
|
+
pt = PrayerTimes.new("Makkah", options)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Help
|
|
71
|
+
|
|
72
|
+
Youre help is appreciated, specially in adjusting the calculation methods and making them more accurate.
|
|
73
|
+
Your contribution is welcome.
|
|
74
|
+
|
|
75
|
+
## Contributing
|
|
76
|
+
|
|
77
|
+
1. Fork it
|
|
78
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
79
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
80
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
81
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
module PrayerTimes
|
|
2
|
+
# Calculation class used to do the times calculation in given settings
|
|
3
|
+
class Calculation
|
|
4
|
+
extend Forwardable
|
|
5
|
+
include MathHelpers
|
|
6
|
+
|
|
7
|
+
def_delegators :@calculator, :time_suffixes, :time_format, :invalid_time, :iterations_count, :times_offsets
|
|
8
|
+
|
|
9
|
+
# Gets the prayers times
|
|
10
|
+
# @param [PrayTime] calculator parent class
|
|
11
|
+
# @param [Date] date the desired date
|
|
12
|
+
# It accepts an array as well [year, month, day]
|
|
13
|
+
# @param [Array] coords of type [long, lat [,alt]]
|
|
14
|
+
# @param [Integer] time_zone the time zone
|
|
15
|
+
def initialize(calculator, date, coords, time_zone)
|
|
16
|
+
self.calculator = calculator
|
|
17
|
+
self.lat = coords[0]
|
|
18
|
+
self.lng = coords[1]
|
|
19
|
+
self.elv = coords.size > 2 ? coords[2] : 0
|
|
20
|
+
self.time_zone = time_zone
|
|
21
|
+
date = Date.new(date[0], date[1], date[2]) unless date.is_a? Date
|
|
22
|
+
self.jdate = date.ajd.to_f - lng / (15 * 24.0)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Compute prayer times
|
|
26
|
+
# @return [Hash] times
|
|
27
|
+
def compute
|
|
28
|
+
times = {
|
|
29
|
+
imsak: 5, fajr: 5, sunrise: 6, dhuhr: 12,
|
|
30
|
+
asr: 13, sunset: 18, maghrib: 18, isha: 18
|
|
31
|
+
}
|
|
32
|
+
# main iterations
|
|
33
|
+
iterations_count.times{times = compute_prayer_times(times)}
|
|
34
|
+
times = adjust_times(times)
|
|
35
|
+
|
|
36
|
+
# add midnight time
|
|
37
|
+
if method_settings[:midnight] == 'Jafari'
|
|
38
|
+
times[:midnight] = times[:sunset] + time_diff(times[:sunset], times[:fajr]) / 2
|
|
39
|
+
else
|
|
40
|
+
times[:midnight] = times[:sunset] + time_diff(times[:sunset], times[:sunrise]) / 2
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
times = tune_times(times)
|
|
44
|
+
modify_formats(times)
|
|
45
|
+
set_names(times)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
attr_accessor :calculator, :time_zone, :lat, :lng, :elv, :jdate
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# convert float time to the given format (see time_formats)
|
|
54
|
+
def get_formatted_time(time)
|
|
55
|
+
return invalid_time if time.nan?
|
|
56
|
+
return time if time_format == 'Float'
|
|
57
|
+
time = fix_hour(time + 0.5 / 60) # add 0.5 minutes to round
|
|
58
|
+
hours = time.floor
|
|
59
|
+
minutes = ((time - hours) * 60).floor
|
|
60
|
+
suffix = time_format == '12h' ? time_suffixes[hours < 12 ? :am : :pm ] : ''
|
|
61
|
+
formatted_time = (time_format == "24h") ? ("%02d:%02d" % [hours, minutes]) : "%d:%02d" % [((hours + 11) % 12)+1, minutes]
|
|
62
|
+
formatted_time + suffix
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# compute mid-day time
|
|
66
|
+
def mid_day(time)
|
|
67
|
+
eqt = sun_position(jdate + time)[1]
|
|
68
|
+
fix_hour(12 - eqt)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# compute the time at which sun reaches a specific angle below horizon
|
|
72
|
+
def sun_angle_time(angle, time, direction = nil)
|
|
73
|
+
decl = sun_position(jdate + time)[0]
|
|
74
|
+
noon = mid_day(time)
|
|
75
|
+
t = 1/15.0 * darccos((-rsin(angle)- rsin(decl)* rsin(lat))/
|
|
76
|
+
(rcos(decl) * rcos(lat)))
|
|
77
|
+
return noon + (direction == 'ccw' ? -t : t)
|
|
78
|
+
rescue
|
|
79
|
+
return (0/0.0)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# compute asr time
|
|
83
|
+
def asr_time(factor, time)
|
|
84
|
+
decl = sun_position(jdate + time)[0]
|
|
85
|
+
angle = -darccot(factor + rtan(lat - decl).abs)
|
|
86
|
+
sun_angle_time(angle, time)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# compute declination angle of sun and equation of time
|
|
90
|
+
# Ref: http://aa.usno.navy.mil/faq/docs/SunApprox.php
|
|
91
|
+
def sun_position(jd)
|
|
92
|
+
d = jd - 2451545.0
|
|
93
|
+
g = fix_angle(357.529 + 0.98560028 * d)
|
|
94
|
+
q = fix_angle(280.459 + 0.98564736 * d)
|
|
95
|
+
l = fix_angle(q + 1.915* rsin(g) + 0.020* rsin(2*g))
|
|
96
|
+
|
|
97
|
+
#r = 1.00014 - 0.01671 * cos(g) - 0.00014 * cos(2*g)
|
|
98
|
+
e = 23.439 - 0.00000036 * d
|
|
99
|
+
|
|
100
|
+
ra = darctan2(rcos(e)* rsin(l), rcos(l))/ 15.0
|
|
101
|
+
eqt = q / 15.0 - fix_hour(ra)
|
|
102
|
+
decl = darcsin(rsin(e)* rsin(l))
|
|
103
|
+
|
|
104
|
+
[decl, eqt]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
# compute prayer times at given julian date
|
|
109
|
+
def compute_prayer_times(times)
|
|
110
|
+
day_portion(times)
|
|
111
|
+
{
|
|
112
|
+
imsak: sun_angle_time(method_settings[:imsak].to_f, times[:imsak], 'ccw'),
|
|
113
|
+
fajr: sun_angle_time(method_settings[:fajr].to_f, times[:fajr], 'ccw'),
|
|
114
|
+
sunrise: sun_angle_time(rise_set_angle(elv), times[:sunrise], 'ccw'),
|
|
115
|
+
dhuhr: mid_day(times[:dhuhr]),
|
|
116
|
+
asr: asr_time(asr_factor(method_settings[:asr]), times[:asr]),
|
|
117
|
+
sunset: sun_angle_time(rise_set_angle(elv), times[:sunset]),
|
|
118
|
+
maghrib: sun_angle_time(method_settings[:maghrib].to_f, times[:maghrib]),
|
|
119
|
+
isha: sun_angle_time(method_settings[:isha].to_f, times[:isha])
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# adjust times in a prayer time array
|
|
124
|
+
def adjust_times(times)
|
|
125
|
+
tz_adjust = time_zone - lng / 15.0
|
|
126
|
+
times.keys.each{|k| times[k] += tz_adjust}
|
|
127
|
+
if !method_settings[:high_lats].nil?
|
|
128
|
+
times = adjust_high_lats(times)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
if minute?(method_settings[:imsak])
|
|
132
|
+
times[:imsak] = times[:fajr] - method_settings[:imsak].to_f / 60.0
|
|
133
|
+
end
|
|
134
|
+
# need to ask about 'min' settings
|
|
135
|
+
if minute?(method_settings[:maghrib])
|
|
136
|
+
times[:maghrib] = times[:sunset] + method_settings[:maghrib].to_f / 60.0
|
|
137
|
+
end
|
|
138
|
+
if minute?(method_settings[:isha])
|
|
139
|
+
times[:isha] = times[:maghrib] + method_settings[:isha].to_f / 60.0
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
times[:dhuhr] += method_settings[:dhuhr].to_f / 60.0
|
|
143
|
+
|
|
144
|
+
return times
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# get asr shadow factor
|
|
148
|
+
def asr_factor(asr)
|
|
149
|
+
calc_methods = {'Standard' => 1, 'Hanafi' => 2}
|
|
150
|
+
calc_methods.include?(asr) ? calc_methods[asr] : asr.to_f
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# return sun angle for sunset/sunrise
|
|
154
|
+
def rise_set_angle(elevation = 0)
|
|
155
|
+
0.833 + 0.0347 * Math.sqrt(elevation) # an approximation
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# apply offsets to the times
|
|
159
|
+
def tune_times(times)
|
|
160
|
+
times.each{|k,_| times[k] += (method_offsets[k] + times_offsets[k]) / 60.0}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# convert times to given time format
|
|
164
|
+
def modify_formats(times)
|
|
165
|
+
times.each{|k,_| times[k] = get_formatted_time(times[k])}
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def set_names(times)
|
|
169
|
+
res = {}
|
|
170
|
+
calculator.times_names.each{|k,v| res[v] = times[k]}
|
|
171
|
+
res
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# adjust times for locations in higher latitudes
|
|
175
|
+
def adjust_high_lats(times)
|
|
176
|
+
night_time = time_diff(times[:sunset], times[:sunrise]) # sunset to sunrise
|
|
177
|
+
times[:imsak] = adjust_hl_time(times[:imsak], times[:sunrise], method_settings[:imsak].to_f, night_time, 'ccw')
|
|
178
|
+
times[:fajr] = adjust_hl_time(times[:fajr], times[:sunrise], method_settings[:fajr].to_f, night_time, 'ccw')
|
|
179
|
+
times[:isha] = adjust_hl_time(times[:isha], times[:sunset], method_settings[:isha].to_f, night_time)
|
|
180
|
+
times[:maghrib] = adjust_hl_time(times[:maghrib], times[:sunset], method_settings[:maghrib].to_f, night_time)
|
|
181
|
+
times
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# adjust a time for higher latitudes
|
|
185
|
+
def adjust_hl_time(time, base, angle, night, direction = nil)
|
|
186
|
+
portion = night_portion(angle, night)
|
|
187
|
+
diff = direction == 'ccw' ? time_diff(time, base) : time_diff(base, time)
|
|
188
|
+
if time.nan? or (diff > portion)
|
|
189
|
+
time = base + (direction == 'ccw' ? - portion : portion)
|
|
190
|
+
end
|
|
191
|
+
time
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# the night portion used for adjusting times in higher latitudes
|
|
195
|
+
def night_portion(angle, night)
|
|
196
|
+
hl_method = method_settings[:high_lats]
|
|
197
|
+
portion = 1/2.0 # midnight
|
|
198
|
+
portion = 1/60.0 * angle if hl_method == 'AngleBased'
|
|
199
|
+
portion = 1/7.0 if hl_method == 'OneSeventh'
|
|
200
|
+
portion * night
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# convert hours to day portions
|
|
204
|
+
def day_portion(times)
|
|
205
|
+
times.each{|k,v| times[k] = times[k] / 24.0}
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# compute the difference between two times
|
|
209
|
+
def time_diff(time1, time2); fix_hour(time2 - time1); end
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# detect if input contains 'min'
|
|
213
|
+
def minute?(arg); arg.to_s.include? "min"; end
|
|
214
|
+
|
|
215
|
+
def fix_hour(hour); fix(hour, 24.0) ; end
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def fix_angle(angle); fix(angle, 360.0) ; end
|
|
219
|
+
|
|
220
|
+
def fix(a, mode)
|
|
221
|
+
return a if a.nan?
|
|
222
|
+
a = a - mode * (a / mode).floor
|
|
223
|
+
a < 0 ? a + mode : a
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def method_settings
|
|
227
|
+
@m_settings ||= calculator.calculation_method.settings
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def method_offsets
|
|
231
|
+
@m_offsets ||= calculator.calculation_method.offsets
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module PrayerTimes
|
|
2
|
+
# Calculation method instances and logic is encapsulated here
|
|
3
|
+
class CalculationMethod
|
|
4
|
+
attr_reader :name, :description, :settings, :offsets
|
|
5
|
+
attr_writer :description
|
|
6
|
+
|
|
7
|
+
# Default settings
|
|
8
|
+
def self.default_settings
|
|
9
|
+
{
|
|
10
|
+
imsak: '10 min',
|
|
11
|
+
dhuhr: '0 min',
|
|
12
|
+
asr: 'Standard',
|
|
13
|
+
maghrib: '0 min',
|
|
14
|
+
midnight: 'Standard',
|
|
15
|
+
high_lats: 'NightMiddle'
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Initializer
|
|
20
|
+
# @param [String] name
|
|
21
|
+
# @param [String] description
|
|
22
|
+
# @param [Hash] settings
|
|
23
|
+
# @option settings [String] :imsak
|
|
24
|
+
# @option settings [String] :fajr
|
|
25
|
+
# @option settings [String] :sunrise
|
|
26
|
+
# @option settings [String] :dhuhr
|
|
27
|
+
# @option settings [String] :asr Asr Juristic Methods:
|
|
28
|
+
# 'Standard': Shafi`i, Maliki, Ja`fari and Hanbali,
|
|
29
|
+
# 'Hanafi': Hanafi
|
|
30
|
+
# @option settings [String] :sunset
|
|
31
|
+
# @option settings [String] :maghrib
|
|
32
|
+
# @option settings [String] :isha
|
|
33
|
+
# @option settings [String] :midnight Midnight Mode:
|
|
34
|
+
# 'Standard': Mid Sunset to Sunrise,
|
|
35
|
+
# 'Jafari': Mid Sunset to Fajr
|
|
36
|
+
# @option settings [String] :high_lights Adjust Methods for Higher Latitudes:
|
|
37
|
+
# 'NightMiddle': middle of night,
|
|
38
|
+
# 'AngleBased': angle/60th of night,
|
|
39
|
+
# 'OneSeventh': 1/7th of night,
|
|
40
|
+
# 'None'
|
|
41
|
+
# @param [Hash] offsets
|
|
42
|
+
# @option offsets [String] :imsak
|
|
43
|
+
# @option offsets [String] :fajr
|
|
44
|
+
# @option offsets [String] :sunrise
|
|
45
|
+
# @option offsets [String] :dhuhr
|
|
46
|
+
# @option offsets [String] :asr
|
|
47
|
+
# @option offsets [String] :sunset
|
|
48
|
+
# @option offsets [String] :maghrib
|
|
49
|
+
# @option offsets [String] :isha
|
|
50
|
+
# @option offsets [String] :midnight
|
|
51
|
+
def initialize(name,description,settings={}, offsets = {})
|
|
52
|
+
self.name = name
|
|
53
|
+
self.description = description
|
|
54
|
+
self.settings = settings
|
|
55
|
+
self.offsets = offsets
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Sets times settings
|
|
59
|
+
# @param [Hash] settings
|
|
60
|
+
# Check the initializer
|
|
61
|
+
def settings=(settings)
|
|
62
|
+
s = settings.reject{|k,v| !(Constants.times_names.key?(k))} rescue {}
|
|
63
|
+
@settings = self.class.default_settings.merge(s)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Sets times offsets
|
|
67
|
+
# @param [Hash] offsets
|
|
68
|
+
# Check the initializer
|
|
69
|
+
def offsets=(offsets)
|
|
70
|
+
s = offsets.reject{|k,v| !(Constants.times_offsets.key?(k) and v.is_a?(Numeric))} rescue {}
|
|
71
|
+
@offsets = Constants.times_offsets.merge(s)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# @return readable representation of this object
|
|
76
|
+
def to_s
|
|
77
|
+
name
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
attr_writer :name
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
module PrayerTimes
|
|
2
|
+
# Helper class to initiate a list of calculation methods and add/update others
|
|
3
|
+
class CalculationMethods
|
|
4
|
+
extend Forwardable
|
|
5
|
+
def_delegators :@hash, :[], :length, :each, :key?, :keys, :delete, :to_s
|
|
6
|
+
|
|
7
|
+
# default methods defined in this gem
|
|
8
|
+
# Methods MWL, ISNA, Egypt, Makkah, Karachi, Tehran and Jafari are accurate
|
|
9
|
+
# Other methods need validation. Your help is appreciated.
|
|
10
|
+
def self.default_methods
|
|
11
|
+
{
|
|
12
|
+
"MWL" =>{
|
|
13
|
+
desc: 'Muslim World League',
|
|
14
|
+
settings: {fajr: 18, isha: 17}
|
|
15
|
+
},
|
|
16
|
+
'ISNA' => {
|
|
17
|
+
desc: 'Islamic Society of North America (ISNA)',
|
|
18
|
+
settings: {fajr: 15, isha: 15}
|
|
19
|
+
},
|
|
20
|
+
'Egypt' => {
|
|
21
|
+
desc: 'Egyptian General Authority of Survey',
|
|
22
|
+
settings: {fajr: 19.5, isha: 17.5}
|
|
23
|
+
},
|
|
24
|
+
'Makkah' => {
|
|
25
|
+
desc: 'Umm Al-Qura University, Makkah',
|
|
26
|
+
settings: {fajr: 18.5, isha: '90 min'} # fajr was 19 degrees before 1430 hijri
|
|
27
|
+
},
|
|
28
|
+
'Karachi' => {
|
|
29
|
+
desc: 'University of Islamic Sciences, Karachi',
|
|
30
|
+
settings: {fajr: 18, isha: 18}
|
|
31
|
+
},
|
|
32
|
+
'Tehran' => {
|
|
33
|
+
desc: 'Institute of Geophysics, University of Tehran',
|
|
34
|
+
settings: {fajr: 17.7, maghrib: 4.5, isha: 14, midnight: 'Jafari'} # isha is not explicitly specified in this method
|
|
35
|
+
},
|
|
36
|
+
'Jafari' => {
|
|
37
|
+
desc: 'Shia Ithna-Ashari, Leva Institute, Qum',
|
|
38
|
+
settings: {fajr: 16, maghrib: 4, isha: 14, midnight: 'Jafari'}
|
|
39
|
+
},
|
|
40
|
+
'UOIF' =>{
|
|
41
|
+
desc: "UNION DES ORGANISATIONS ISLAMIQUES DE FRANCE",
|
|
42
|
+
settings: {fajr: 19, maghrib: '0 min', isha: 17}
|
|
43
|
+
},
|
|
44
|
+
'Algeria' =>{
|
|
45
|
+
desc: "Algeria",
|
|
46
|
+
settings: {fajr: 18, maghrib: '3 min', isha: 17}
|
|
47
|
+
},
|
|
48
|
+
'EmirateDubai' =>{
|
|
49
|
+
desc: "Emirate, Dubai",
|
|
50
|
+
settings: {fajr: 18.5, maghrib: '0 min', isha: '90 min'},
|
|
51
|
+
offsets: {dhuhr: 4, asr: 5, maghrib: 2}
|
|
52
|
+
},
|
|
53
|
+
'Emirates' =>{
|
|
54
|
+
desc: "Emirates",
|
|
55
|
+
settings: {fajr: 18.5, maghrib: '0 min', isha: '90 min'},
|
|
56
|
+
offsets: {asr: 4, maghrib: 2}
|
|
57
|
+
},
|
|
58
|
+
'EnglandBirmingham' =>{
|
|
59
|
+
desc: "England, Birmingham",
|
|
60
|
+
settings: {fajr: 5, maghrib: '0 min', isha: 84},
|
|
61
|
+
offsets: {fajr: -60, isha: 60}
|
|
62
|
+
},
|
|
63
|
+
'Jordan' =>{
|
|
64
|
+
desc: "General Iftaa' Department, The Hashemite Kingdom of Jordan",
|
|
65
|
+
settings: {fajr: 18, maghrib: '0 min', isha: 18}
|
|
66
|
+
},
|
|
67
|
+
'Kuwait' =>{
|
|
68
|
+
desc: "Kuwait",
|
|
69
|
+
settings: {fajr: 18, maghrib: '0 min', isha: 17.5}
|
|
70
|
+
},
|
|
71
|
+
'Libya' =>{
|
|
72
|
+
desc: "Libya",
|
|
73
|
+
settings: {fajr: 18.5, maghrib: '0 min', isha: 18.5},
|
|
74
|
+
offsets: { dhuhr: 4, maghrib: 4}
|
|
75
|
+
},
|
|
76
|
+
'Malaysia' =>{
|
|
77
|
+
desc: "Malaysia",
|
|
78
|
+
settings: {fajr: 20, maghrib: '0 min', isha: 18},
|
|
79
|
+
offsets: {fajr: 3, sunrise: 2, dhuhr: 1, asr: 2, maghrib: 1, isha: -1}
|
|
80
|
+
},
|
|
81
|
+
'Maldives' =>{
|
|
82
|
+
desc: "Maldives",
|
|
83
|
+
settings: {fajr: 19, maghrib: '0 min', isha: 19},
|
|
84
|
+
offsets: {sunrise: -1, dhuhr: 4, asr: 1, maghrib: 1, isha: 1}
|
|
85
|
+
},
|
|
86
|
+
'Morocco' =>{
|
|
87
|
+
desc: "Morocco",
|
|
88
|
+
settings: {fajr: 19, maghrib: '0 min', isha: 17},
|
|
89
|
+
offsets: {fajr: -1, sunrise: -2, dhuhr: 5, maghrib: 3}
|
|
90
|
+
},
|
|
91
|
+
'Oman' =>{
|
|
92
|
+
desc: "Oman",
|
|
93
|
+
settings: {fajr: 18, maghrib: '5 min', isha: 18},
|
|
94
|
+
offsets: {dhuhr: 5, asr: 5, isha: 1}
|
|
95
|
+
},
|
|
96
|
+
'Qatar' =>{
|
|
97
|
+
desc: "Qatar",
|
|
98
|
+
settings: {fajr: 18, maghrib: '0 min', isha: '90 min'}
|
|
99
|
+
},
|
|
100
|
+
'Tunisia' =>{
|
|
101
|
+
desc: "Tunisia",
|
|
102
|
+
settings: {fajr: 18, maghrib: '1 min', isha: 18},
|
|
103
|
+
offsets: {fajr: -1, sunrise: -2, dhuhr: 8, isha: 1}
|
|
104
|
+
},
|
|
105
|
+
'Turkey' =>{
|
|
106
|
+
desc: "Presidency of Religious Affairs, Turkey",
|
|
107
|
+
settings: {fajr: 18, maghrib: '9 min', isha: 17},
|
|
108
|
+
offsets: {fajr: -2, sunrise: -7, dhuhr: 6, asr: 4, isha: 2}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Initializer
|
|
114
|
+
# it populates a hash with predefined set of methods
|
|
115
|
+
def initialize
|
|
116
|
+
self.hash = {}
|
|
117
|
+
populate
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @param [String] name
|
|
121
|
+
# @param [String] description
|
|
122
|
+
# @param [Hash] settings
|
|
123
|
+
# @param [Hash] offsets
|
|
124
|
+
# @see CalculationMethod
|
|
125
|
+
def add(name, description, settings={}, offsets={})
|
|
126
|
+
hash[name] = CalculationMethod.new(name, description, settings, offsets)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Names of the available methods
|
|
130
|
+
# @return [Array] list of names
|
|
131
|
+
def names
|
|
132
|
+
keys
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
attr_accessor :hash
|
|
138
|
+
|
|
139
|
+
def populate
|
|
140
|
+
self.class.default_methods.each {|k,v| add(k, v[:desc], v[:settings], v[:offsets])}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module PrayerTimes
|
|
2
|
+
# This is main interface class
|
|
3
|
+
class Calculator
|
|
4
|
+
include Setters
|
|
5
|
+
|
|
6
|
+
attr_reader :calculation_method, :time_format, :times_names, :time_suffixes, :invalid_time, :iterations_count, :times_offsets
|
|
7
|
+
|
|
8
|
+
# Initializer
|
|
9
|
+
# @param [String] calc_method the calculation method to use
|
|
10
|
+
# @param [Hash] opts formatting options
|
|
11
|
+
# @option opts [String] :time_format
|
|
12
|
+
# @option opts [String] :invalid_time
|
|
13
|
+
# @option opts [String] :time_suffixes
|
|
14
|
+
# @option opts [String] :times_names
|
|
15
|
+
# @option opts [String] :times_offsets
|
|
16
|
+
# @option opts [String] :iterations_count this is algorithmic option. Don't set it unless you know what you are doing
|
|
17
|
+
# @see Setters to get an idea about those options
|
|
18
|
+
def initialize(calc_method, opts)
|
|
19
|
+
self.calculation_method = calc_method
|
|
20
|
+
|
|
21
|
+
self.time_format = opts[:time_format]
|
|
22
|
+
|
|
23
|
+
self.invalid_time = opts[:invalid_time]
|
|
24
|
+
|
|
25
|
+
self.time_suffixes = (opts[:time_suffixes])
|
|
26
|
+
|
|
27
|
+
self.times_names = (opts[:times_names])
|
|
28
|
+
|
|
29
|
+
self.times_offsets = (opts[:times_offsets])
|
|
30
|
+
|
|
31
|
+
self.iterations_count = opts[:iterations_count]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Gets the prayers times
|
|
37
|
+
# @param [Date] date the date
|
|
38
|
+
# @param [Array] coords of type [long, lat [,alt]]
|
|
39
|
+
# @param [Integer] time_zone the time zone
|
|
40
|
+
# @param [Integer] dst Daylight saving time
|
|
41
|
+
# @return [Hash] times
|
|
42
|
+
def get_times(date, coords, time_zone, dst = nil)
|
|
43
|
+
Calculation.new(self,
|
|
44
|
+
date,
|
|
45
|
+
coords,
|
|
46
|
+
time_zone + (dst.nil? ? 0 : 1)).
|
|
47
|
+
compute
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def const_class
|
|
53
|
+
PrayerTimes
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|