Skip to content

Commit 6f3cf67

Browse files
Merge branch 'add_tools_tests' into dep_management
2 parents b02f090 + 545c196 commit 6f3cf67

File tree

3 files changed

+201
-7
lines changed

3 files changed

+201
-7
lines changed

docs/sphinx/source/whatsnew/v0.11.3.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Documentation
1818

1919
Testing
2020
~~~~~~~
21+
* Add tests for time conversions in tools package. (:issue:`2340`, :pull:`2341`)
2122

2223

2324
Requirements
@@ -26,5 +27,4 @@ Requirements
2627

2728
Contributors
2829
~~~~~~~~~~~~
29-
30-
30+
* Mark Campanellli (:ghuser:`markcampanelli`)

pvlib/tests/test_tools.py

Lines changed: 197 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import pytest
1+
from datetime import datetime
2+
from zoneinfo import ZoneInfo
23

3-
from pvlib import tools
44
import numpy as np
5-
import pandas as pd
65
from numpy.testing import assert_allclose
6+
import pandas as pd
7+
import pytest
8+
9+
from pvlib import location, tools
710

811

912
@pytest.mark.parametrize('keys, input_dict, expected', [
@@ -144,3 +147,194 @@ def test_get_pandas_index(args, args_idx):
144147
def test_normalize_max2one(data_in, expected):
145148
result = tools.normalize_max2one(data_in)
146149
assert_allclose(result, expected)
150+
151+
152+
@pytest.mark.parametrize(
153+
'input,expected',
154+
[
155+
(
156+
{
157+
"time": datetime(
158+
1974, 6, 22, 18, 30, 15, tzinfo=ZoneInfo("Etc/GMT+5"),
159+
),
160+
"location": location.Location(
161+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
162+
)
163+
},
164+
datetime(1974, 6, 22, 23, 30, 15, tzinfo=ZoneInfo("UTC")),
165+
),
166+
(
167+
{
168+
"time": datetime(1974, 6, 22, 18, 30, 15),
169+
"location": location.Location(
170+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
171+
)
172+
},
173+
datetime(1974, 6, 22, 23, 30, 15, tzinfo=ZoneInfo("UTC")),
174+
),
175+
(
176+
{
177+
"time": pd.DatetimeIndex(
178+
["1974-06-22T18:30:15"],
179+
tz=ZoneInfo("Etc/GMT+5"),
180+
),
181+
"location": location.Location(
182+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
183+
)
184+
},
185+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
186+
),
187+
(
188+
{
189+
"time": pd.DatetimeIndex(["1974-06-22T18:30:15"]),
190+
"location": location.Location(
191+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
192+
)
193+
},
194+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
195+
),
196+
(
197+
{
198+
"time": pd.Series(
199+
[24.42],
200+
index=pd.DatetimeIndex(
201+
["1974-06-22T18:30:15"],
202+
tz=ZoneInfo("Etc/GMT+5"),
203+
),
204+
),
205+
"location": location.Location(
206+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
207+
)
208+
},
209+
pd.Series(
210+
[24.42],
211+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
212+
),
213+
),
214+
(
215+
{
216+
"time": pd.Series(
217+
[24.42],
218+
index=pd.DatetimeIndex(["1974-06-22T18:30:15"]),
219+
),
220+
"location": location.Location(
221+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
222+
)
223+
},
224+
pd.Series(
225+
[24.42],
226+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
227+
),
228+
),
229+
(
230+
{
231+
"time": pd.DataFrame(
232+
[[24.42]],
233+
index=pd.DatetimeIndex(
234+
["1974-06-22T18:30:15"],
235+
tz=ZoneInfo("Etc/GMT+5"),
236+
),
237+
),
238+
"location": location.Location(
239+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
240+
)
241+
},
242+
pd.DataFrame(
243+
[[24.42]],
244+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
245+
),
246+
),
247+
(
248+
{
249+
"time": pd.DataFrame(
250+
[[24.42]],
251+
index=pd.DatetimeIndex(["1974-06-22T18:30:15"]),
252+
),
253+
"location": location.Location(
254+
43.19262774396091, -77.58782907414867, tz="Etc/GMT+5"
255+
)
256+
},
257+
pd.DataFrame(
258+
[[24.42]],
259+
pd.DatetimeIndex(["1974-06-22T23:30:15"], tz=ZoneInfo("UTC")),
260+
),
261+
),
262+
],
263+
ids=[
264+
"datetime.datetime with tzinfo",
265+
"datetime.datetime",
266+
"pandas.DatetimeIndex with tzinfo",
267+
"pandas.DatetimeIndex",
268+
"pandas.Series with tzinfo",
269+
"pandas.Series",
270+
"pandas.DataFrame with tzinfo",
271+
"pandas.DataFrame",
272+
],
273+
)
274+
def test_localize_to_utc(input, expected):
275+
got = tools.localize_to_utc(**input)
276+
277+
if isinstance(got, (pd.Series, pd.DataFrame)):
278+
# Older pandas versions have wonky dtype equality check on timestamp
279+
# index, so check the values as numpy.ndarray and indices one by one.
280+
np.testing.assert_array_equal(got.to_numpy(), expected.to_numpy())
281+
282+
for index_got, index_expected in zip(got.index, expected.index):
283+
assert index_got == index_expected
284+
else:
285+
assert got == expected
286+
287+
288+
@pytest.mark.parametrize(
289+
'input,expected',
290+
[
291+
(
292+
{
293+
"time": datetime(
294+
1974, 6, 22, 18, 30, 15, tzinfo=ZoneInfo("Etc/GMT+5")
295+
)
296+
},
297+
27201.47934027778,
298+
),
299+
(
300+
{
301+
"time": datetime(
302+
1974, 6, 22, 23, 30, 15, tzinfo=ZoneInfo("UTC")
303+
)
304+
},
305+
27201.47934027778,
306+
),
307+
],
308+
ids=["datetime.datetime with tzinfo", "datetime.datetime"],
309+
)
310+
def test_datetime_to_djd(input, expected):
311+
assert tools.datetime_to_djd(input["time"]) == expected
312+
313+
314+
@pytest.mark.parametrize(
315+
'input,expected',
316+
[
317+
(
318+
{
319+
"djd": 27201.47934027778,
320+
"tz": "Etc/GMT+5",
321+
},
322+
datetime(1974, 6, 22, 18, 30, 15, tzinfo=ZoneInfo("Etc/GMT+5")),
323+
),
324+
(
325+
{
326+
"djd": 27201.47934027778,
327+
"tz": None,
328+
},
329+
datetime(1974, 6, 22, 23, 30, 15, tzinfo=ZoneInfo("UTC")),
330+
),
331+
],
332+
ids=["djd with tzinfo", "djd"],
333+
)
334+
def test_djd_to_datetime(input, expected):
335+
if input["tz"] is not None:
336+
got = tools.djd_to_datetime(input["djd"])
337+
else:
338+
got = tools.djd_to_datetime(input["djd"], tz="Etc/GMT+5")
339+
340+
assert got == expected

pvlib/tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def atand(number):
119119

120120
def localize_to_utc(time, location):
121121
"""
122-
Converts or localizes a time series to UTC.
122+
Converts time to UTC, localizing if necessary using location.
123123
124124
Parameters
125125
----------
@@ -129,7 +129,7 @@ def localize_to_utc(time, location):
129129
130130
Returns
131131
-------
132-
pandas object localized to UTC.
132+
datetime.datetime or pandas object localized to UTC.
133133
"""
134134
if isinstance(time, dt.datetime):
135135
if time.tzinfo is None:

0 commit comments

Comments
 (0)