1import datetime
2
3import freezegun
4import pytest
5from astral import Observer, sun, today
6
7
8@pytest.mark.parametrize(
9    "day,jd",
10    [
11        (datetime.date(2012, 1, 1), 2455927.5),
12        (datetime.date(2013, 1, 1), 2456293.5),
13        (datetime.date(2013, 6, 1), 2456444.5),
14        (datetime.date(1867, 2, 1), 2402998.5),
15        (datetime.date(3200, 11, 14), 2890153.5),
16    ],
17)
18def test_JulianDay(day: datetime.date, jd: float):
19    assert sun.julianday(day) == jd
20
21
22@pytest.mark.parametrize(
23    "jd,jc",
24    [
25        (2455927.5, 0.119986311),
26        (2456293.5, 0.130006845),
27        (2456444.5, 0.134140999),
28        (2402998.5, -1.329130732),
29        (2890153.5, 12.00844627),
30    ],
31)
32def test_JulianCentury(jd: float, jc: float):
33    assert sun.jday_to_jcentury(jd) == pytest.approx(jc)
34
35
36@pytest.mark.parametrize(
37    "jc,jd",
38    [
39        (0.119986311, 2455927.5),
40        (0.130006845, 2456293.5),
41        (0.134140999, 2456444.5),
42        (-1.329130732, 2402998.5),
43        (12.00844627, 2890153.5),
44    ],
45)
46def test_JulianCenturyToJulianDay(jc: float, jd: float):
47    assert sun.jcentury_to_jday(jc) == pytest.approx(jd)
48
49
50@pytest.mark.parametrize(
51    "jc,gmls",
52    [
53        (-1.329130732, 310.7374254),
54        (12.00844627, 233.8203529),
55        (0.184134155, 69.43779106),
56    ],
57)
58def test_GeomMeanLongSun(jc: float, gmls: float):
59    assert sun.geom_mean_long_sun(jc) == pytest.approx(gmls)
60
61
62@pytest.mark.parametrize(
63    "jc,gmas",
64    [(0.119986311, 4676.922342), (12.00844627, 432650.1681), (0.184134155, 6986.1838),],
65)
66def test_GeomAnomolyLongSun(jc: float, gmas: float):
67    assert sun.geom_mean_anomaly_sun(jc) == pytest.approx(gmas)
68
69
70@pytest.mark.parametrize(
71    "jc,eeo",
72    [
73        (0.119986311, 0.016703588),
74        (12.00844627, 0.016185564),
75        (0.184134155, 0.016700889),
76    ],
77)
78def test_EccentricityEarthOrbit(jc: float, eeo: float):
79    assert sun.eccentric_location_earth_orbit(jc) == pytest.approx(eeo, abs=1e-6)
80
81
82@pytest.mark.parametrize(
83    "jc,eos",
84    [
85        (0.119986311, -0.104951648),
86        (12.00844627, -1.753028843),
87        (0.184134155, 1.046852316),
88    ],
89)
90def test_SunEqOfCenter(jc: float, eos: float):
91    assert sun.sun_eq_of_center(jc) == pytest.approx(eos, abs=1e-6)
92
93
94@pytest.mark.parametrize(
95    "jc,stl",
96    [
97        (0.119986311, 279.9610686),
98        (12.00844627, 232.0673358),
99        (0.184134155, 70.48465428),
100    ],
101)
102def test_SunTrueLong(jc: float, stl: float):
103    assert sun.sun_true_long(jc) == pytest.approx(stl, abs=0.001)
104
105
106@pytest.mark.parametrize(
107    "jc,sta",
108    [
109        (0.119986311, 4676.817391),
110        (12.00844627, 432648.4151),
111        (0.184134155, 6987.230663),
112    ],
113)
114def test_SunTrueAnomaly(jc: float, sta: float):
115    assert sun.sun_true_anomoly(jc) == pytest.approx(sta, abs=0.001)
116
117
118@pytest.mark.parametrize(
119    "jc,srv",
120    [
121        (0.119986311, 0.983322329),
122        (12.00844627, 0.994653382),
123        (0.184134155, 1.013961204),
124    ],
125)
126def test_SunRadVector(jc: float, srv: float):
127    assert sun.sun_rad_vector(jc) == pytest.approx(srv, abs=0.001)
128
129
130@pytest.mark.parametrize(
131    "jc,sal",
132    [
133        (0.119986311, 279.95995849827),
134        (12.00844627, 232.065823531804),
135        (0.184134155, 70.475244256027),
136    ],
137)
138def test_SunApparentLong(jc: float, sal: float):
139    assert sun.sun_apparent_long(jc) == pytest.approx(sal)
140
141
142@pytest.mark.parametrize(
143    "jc,mooe",
144    [
145        (0.119986311, 23.4377307876356),
146        (12.00844627, 23.2839797200388),
147        (0.184134155, 23.4368965974579),
148    ],
149)
150def test_MeanObliquityOfEcliptic(jc: float, mooe: float):
151    assert sun.mean_obliquity_of_ecliptic(jc) == pytest.approx(mooe)
152
153
154@pytest.mark.parametrize(
155    "jc,oc",
156    [
157        (0.119986311, 23.4369810410121),
158        (12.00844627, 23.2852236361575),
159        (0.184134155, 23.4352890293474),
160    ],
161)
162def test_ObliquityCorrection(jc: float, oc: float):
163    assert sun.obliquity_correction(jc) == pytest.approx(oc, abs=0.001)
164
165
166@pytest.mark.parametrize(
167    "jc,sra",
168    [
169        (0.119986311, -79.16480352),
170        (12.00844627, -130.3163904),
171        (0.184134155, 68.86915896),
172    ],
173)
174def test_SunRtAscension(jc: float, sra: float):
175    assert sun.sun_rt_ascension(jc) == pytest.approx(sra, abs=0.001)
176
177
178@pytest.mark.parametrize(
179    "jc,sd",
180    [
181        (0.119986311, -23.06317068),
182        (12.00844627, -18.16694394),
183        (0.184134155, 22.01463552),
184    ],
185)
186def test_SunDeclination(jc: float, sd: float):
187    assert sun.sun_declination(jc) == pytest.approx(sd, abs=0.001)
188
189
190@pytest.mark.parametrize(
191    "jc,eot",
192    [
193        (0.119986311, -3.078194825),
194        (12.00844627, 16.58348133),
195        (0.184134155, 2.232039737),
196    ],
197)
198def test_EquationOfTime(jc: float, eot: float):
199    assert sun.eq_of_time(jc) == pytest.approx(eot)
200
201
202@pytest.mark.parametrize(
203    "d,ha",
204    [
205        (datetime.date(2012, 1, 1), 1.03555238),
206        (datetime.date(3200, 11, 14), 1.172253118),
207        (datetime.date(2018, 6, 1), 2.133712555),
208    ],
209)
210def test_HourAngle(d: datetime.date, ha: float, london):
211    jd = sun.julianday(d)
212    jc = sun.jday_to_jcentury(jd)
213    decl = sun.sun_declination(jc)
214
215    assert sun.hour_angle(
216        london.latitude, decl, 90.8333, sun.SunDirection.RISING
217    ) == pytest.approx(ha, abs=0.001)
218
219
220def test_Azimuth(new_delhi):
221    d = datetime.datetime(2001, 6, 21, 13, 11, 0)
222    assert sun.azimuth(new_delhi, d) == pytest.approx(292.766381632981)
223
224
225def test_Elevation(new_delhi):
226    d = datetime.datetime(2001, 6, 21, 13, 11, 0)
227    assert sun.elevation(new_delhi, d) == pytest.approx(7.411009003716742)
228
229
230def test_Elevation_NonNaive(new_delhi):
231    d = datetime.datetime(2001, 6, 21, 18, 41, 0)
232    d = new_delhi.tz.localize(d)
233    assert sun.elevation(new_delhi, d) == pytest.approx(7.411009003716742)
234
235
236def test_Elevation_WithoutRefraction(new_delhi):
237    d = datetime.datetime(2001, 6, 21, 13, 11, 0)
238    assert sun.elevation(new_delhi, d, with_refraction=False) == pytest.approx(
239        7.293490557358638
240    )
241
242
243def test_Azimuth_Above85Degrees():
244    d = datetime.datetime(2001, 6, 21, 13, 11, 0)
245    assert sun.azimuth(Observer(86, 77.2), d) == pytest.approx(276.2148, abs=0.001)
246
247
248def test_Elevation_Above85Degrees():
249    d = datetime.datetime(2001, 6, 21, 13, 11, 0)
250    assert sun.elevation(Observer(86, 77.2), d) == pytest.approx(
251        23.102501151619506, abs=0.001
252    )
253
254
255@pytest.mark.parametrize("elevation", range(1,10))
256@freezegun.freeze_time("2020-02-06")
257def test_ElevationEqualsTimeAtElevation(elevation, london):
258    o = london.observer
259    td = today()
260    et = sun.time_at_elevation(o, elevation, td)
261    assert sun.elevation(o, et) == pytest.approx(elevation, abs=0.05)
262