prayer_times 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|