-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy path0-root.go
165 lines (134 loc) · 5.35 KB
/
0-root.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package prayer
import (
"time"
)
// Schedule is the time of each prayer (and related events) on a day.
type Schedule struct {
// Date is the ISO date, useful for logging.
Date string
// Fajr is the time when the sky begins to lighten (dawn) after previously
// completely dark.
Fajr time.Time
// Sunrise is the moment when the upper limb of the Sun appears on the horizon
// in the morning.
Sunrise time.Time
// Zuhr is the time when the Sun begins to decline after reaching the highest
// point in the sky, so a bit after solar noon.
Zuhr time.Time
// Asr is the time when the length of any object's shadow reaches a factor of
// the length of the object itself plus the length of that object's shadow at
// noon.
Asr time.Time
// Maghrib is sunset, i.e. the time when the upper limb of the Sun disappears
// below the horizon.
Maghrib time.Time
// Isha is the time when darkness falls and after this point the sky is no longer
// illuminated (dusk).
Isha time.Time
// IsNormal specify whether the day have a normal day night period or not. It
// will be false in area with higher latitude, when Sun never rise or set in
// extreme periods.
IsNormal bool
}
// ScheduleCorrections is correction for each prayer time.
type ScheduleCorrections struct {
Fajr time.Duration
Sunrise time.Duration
Zuhr time.Duration
Asr time.Duration
Maghrib time.Duration
Isha time.Duration
}
// TwilightConvention is the convention that specifies time for Fajr (dawn) and Isha
// (dusk). Most of the conventions use Solar angle elevation for both dawn and dusk
// time, however there are several convention where dusk times depends on sunset
// (Maghrib) times.
type TwilightConvention struct {
FajrAngle float64
IshaAngle float64
MaghribDuration time.Duration
}
// HighLatitudeAdapter is function for calculating prayer times in area with latitude
// >45 degrees. Check out https://www.prayertimes.dk/story.html for why this is needed.
type HighLatitudeAdapter func(cfg Config, year int, currentSchedules []Schedule) []Schedule
// Config is configuration that used to calculate the prayer times.
type Config struct {
// Latitude is the latitude of the location. Positive for north area and negative
// for south area.
Latitude float64
// Longitude is the longitude of the location. Positive for east area and negative
// for west area.
Longitude float64
// Elevation is the elevation of the location above sea level. It's used to
// improve calculation for sunrise and sunset by factoring the value of
// atmospheric refraction. However, apparently most of the prayer time
// calculator doesn't use it so it's fine to omit it.
Elevation float64
// Timezone is the time zone of the location specified above. If not specified,
// it will use UTC.
Timezone *time.Location
// TwilightConvention is the convention that used to specify time for Fajr and
// Isha. By default it will use `AstronomicalTwilight`.
TwilightConvention *TwilightConvention
// AsrConvention is the convention that used for calculating Asr time. There are
// two conventions, Shafii and Hanafi. By default it will use Shafii.
AsrConvention AsrConvention
// HighLatitudeAdapter is the function for adjusting prayer times in area with
// high latitude (>=45 degrees). If not specified, it will not calculate the
// adjustment for higher latitude and instead will return the schedule as it is.
// For area in high or extreme latitude, it might return zero for Fajr, Sunrise,
// Maghrib and Isha.
HighLatitudeAdapter HighLatitudeAdapter
// Corrections is used to corrects calculated time for each specified prayer.
Corrections ScheduleCorrections
// PreciseToSeconds specify whether output time will omit the seconds or not.
PreciseToSeconds bool
}
// Calculate calculates the prayer time for the entire year with specified configuration.
func Calculate(cfg Config, year int) ([]Schedule, error) {
// Apply default config
if cfg.Timezone == nil {
cfg.Timezone = time.UTC
}
if cfg.TwilightConvention == nil {
cfg.TwilightConvention = AstronomicalTwilight()
}
// Calculate the schedules
schedules, nAbnormal := calcNormal(cfg, year)
// Apply high latitude adapter
if nAbnormal > 0 && cfg.HighLatitudeAdapter != nil {
schedules = cfg.HighLatitudeAdapter(cfg, year, schedules)
}
// Final check
fixedMaghribDuration := cfg.TwilightConvention.MaghribDuration
for i, s := range schedules {
// Apply Isha times for convention where Isha time is fixed after Maghrib
if fixedMaghribDuration > 0 {
s.Isha = s.Maghrib.Add(fixedMaghribDuration)
}
// Apply time correction
s.Fajr = applyCorrection(s.Fajr, cfg.Corrections.Fajr)
s.Sunrise = applyCorrection(s.Sunrise, cfg.Corrections.Sunrise)
s.Zuhr = applyCorrection(s.Zuhr, cfg.Corrections.Zuhr)
s.Asr = applyCorrection(s.Asr, cfg.Corrections.Asr)
s.Maghrib = applyCorrection(s.Maghrib, cfg.Corrections.Maghrib)
s.Isha = applyCorrection(s.Isha, cfg.Corrections.Isha)
// If needed round the time to minute
if !cfg.PreciseToSeconds {
s.Fajr = s.Fajr.Round(time.Minute)
s.Sunrise = s.Sunrise.Round(time.Minute)
s.Zuhr = s.Zuhr.Round(time.Minute)
s.Asr = s.Asr.Round(time.Minute)
s.Maghrib = s.Maghrib.Round(time.Minute)
s.Isha = s.Isha.Round(time.Minute)
}
schedules[i] = s
}
return schedules, nil
}
func applyCorrection(t time.Time, d time.Duration) time.Time {
if !t.IsZero() {
t = t.Add(d)
}
return t
}