@@ -25,19 +25,15 @@ def make_constant_readings(
2525 base_time : datetime , temperature : float , hours : int = 24
2626) -> list [tuple [datetime , float ]]:
2727 """Generate readings with constant temperature over a period."""
28- return [
29- (base_time + timedelta (hours = h ), temperature )
30- for h in range (hours + 1 )
31- ]
28+ return [(base_time + timedelta (hours = h ), temperature ) for h in range (hours + 1 )]
3229
3330
3431def make_readings_from_hourly_temps (
3532 base_time : datetime , hourly_temps : list [float ]
3633) -> list [tuple [datetime , float ]]:
3734 """Generate readings from a list of hourly temperatures."""
3835 return [
39- (base_time + timedelta (hours = h ), temp )
40- for h , temp in enumerate (hourly_temps )
36+ (base_time + timedelta (hours = h ), temp ) for h , temp in enumerate (hourly_temps )
4137 ]
4238
4339
@@ -126,8 +122,7 @@ def test_linear_temperature_decrease(self, base_time):
126122 """Linear temperature decrease throughout the day."""
127123 # From 18°C to 8°C over 24 hours
128124 readings = [
129- (base_time + timedelta (hours = h ), 18.0 - (h * 10 / 24 ))
130- for h in range (25 )
125+ (base_time + timedelta (hours = h ), 18.0 - (h * 10 / 24 )) for h in range (25 )
131126 ]
132127 result = calculate_hdd_from_readings (readings , base_temp = 18.0 )
133128 # Average deficit over the day: ~5°C -> ~5 HDD
@@ -137,10 +132,31 @@ def test_diurnal_cycle(self, base_time):
137132 """Simulate a typical day/night temperature cycle."""
138133 # Night: cold, Day: warmer
139134 hourly_temps = [
140- 5 , 4 , 3 , 3 , 4 , 5 , # 00:00-05:00 (cold night)
141- 7 , 9 , 12 , 15 , 17 , 19 , # 06:00-11:00 (warming up)
142- 20 , 21 , 21 , 20 , 18 , 16 , # 12:00-17:00 (warm afternoon)
143- 14 , 12 , 10 , 8 , 7 , 6 , 5 # 18:00-24:00 (cooling down)
135+ 5 ,
136+ 4 ,
137+ 3 ,
138+ 3 ,
139+ 4 ,
140+ 5 , # 00:00-05:00 (cold night)
141+ 7 ,
142+ 9 ,
143+ 12 ,
144+ 15 ,
145+ 17 ,
146+ 19 , # 06:00-11:00 (warming up)
147+ 20 ,
148+ 21 ,
149+ 21 ,
150+ 20 ,
151+ 18 ,
152+ 16 , # 12:00-17:00 (warm afternoon)
153+ 14 ,
154+ 12 ,
155+ 10 ,
156+ 8 ,
157+ 7 ,
158+ 6 ,
159+ 5 , # 18:00-24:00 (cooling down)
144160 ]
145161 readings = make_readings_from_hourly_temps (base_time , hourly_temps )
146162 result = calculate_hdd_from_readings (readings , base_temp = 18.0 )
@@ -210,10 +226,31 @@ def test_hot_summer_day_cycle(self, base_time):
210226 """Simulate a hot summer day with diurnal cycle."""
211227 # Night: warm, Day: hot
212228 hourly_temps = [
213- 22 , 21 , 20 , 19 , 19 , 20 , # 00:00-05:00 (warm night)
214- 22 , 25 , 28 , 31 , 33 , 35 , # 06:00-11:00 (heating up)
215- 36 , 37 , 37 , 36 , 34 , 32 , # 12:00-17:00 (hot afternoon)
216- 30 , 28 , 26 , 24 , 23 , 22 , 22 # 18:00-24:00 (cooling)
229+ 22 ,
230+ 21 ,
231+ 20 ,
232+ 19 ,
233+ 19 ,
234+ 20 , # 00:00-05:00 (warm night)
235+ 22 ,
236+ 25 ,
237+ 28 ,
238+ 31 ,
239+ 33 ,
240+ 35 , # 06:00-11:00 (heating up)
241+ 36 ,
242+ 37 ,
243+ 37 ,
244+ 36 ,
245+ 34 ,
246+ 32 , # 12:00-17:00 (hot afternoon)
247+ 30 ,
248+ 28 ,
249+ 26 ,
250+ 24 ,
251+ 23 ,
252+ 22 ,
253+ 22 , # 18:00-24:00 (cooling)
217254 ]
218255 readings = make_readings_from_hourly_temps (base_time , hourly_temps )
219256 result = calculate_cdd_from_readings (readings , base_temp = 18.0 )
@@ -322,8 +359,7 @@ def test_linear_increase_integration(self, base_time):
322359 """Linear temperature increase should integrate correctly."""
323360 # Temperature increases linearly from 10°C to 20°C over 24h
324361 readings = [
325- (base_time + timedelta (hours = h ), 10.0 + (h * 10 / 24 ))
326- for h in range (25 )
362+ (base_time + timedelta (hours = h ), 10.0 + (h * 10 / 24 )) for h in range (25 )
327363 ]
328364 result = calculate_hdd_from_readings (readings , base_temp = 18.0 )
329365 # Average temp = 15°C, but only part below 18°C contributes
@@ -356,10 +392,31 @@ class TestRealWorldScenarios:
356392 def test_winter_day_france (self , base_time ):
357393 """Typical winter day in France (January)."""
358394 hourly_temps = [
359- 2 , 1 , 0 , 0 , - 1 , 0 , # 00:00-05:00
360- 1 , 2 , 4 , 6 , 8 , 9 , # 06:00-11:00
361- 10 , 10 , 9 , 8 , 6 , 4 , # 12:00-17:00
362- 3 , 2 , 2 , 1 , 1 , 1 , 2 # 18:00-24:00
395+ 2 ,
396+ 1 ,
397+ 0 ,
398+ 0 ,
399+ - 1 ,
400+ 0 , # 00:00-05:00
401+ 1 ,
402+ 2 ,
403+ 4 ,
404+ 6 ,
405+ 8 ,
406+ 9 , # 06:00-11:00
407+ 10 ,
408+ 10 ,
409+ 9 ,
410+ 8 ,
411+ 6 ,
412+ 4 , # 12:00-17:00
413+ 3 ,
414+ 2 ,
415+ 2 ,
416+ 1 ,
417+ 1 ,
418+ 1 ,
419+ 2 , # 18:00-24:00
363420 ]
364421 readings = make_readings_from_hourly_temps (base_time , hourly_temps )
365422 result = calculate_hdd_from_readings (readings , base_temp = 18.0 )
@@ -370,10 +427,31 @@ def test_winter_day_france(self, base_time):
370427 def test_summer_day_france (self , base_time ):
371428 """Typical summer day in France (July)."""
372429 hourly_temps = [
373- 18 , 17 , 16 , 16 , 17 , 18 , # 00:00-05:00
374- 20 , 23 , 26 , 28 , 30 , 32 , # 06:00-11:00
375- 33 , 34 , 34 , 33 , 31 , 29 , # 12:00-17:00
376- 27 , 25 , 23 , 21 , 20 , 19 , 18 # 18:00-24:00
430+ 18 ,
431+ 17 ,
432+ 16 ,
433+ 16 ,
434+ 17 ,
435+ 18 , # 00:00-05:00
436+ 20 ,
437+ 23 ,
438+ 26 ,
439+ 28 ,
440+ 30 ,
441+ 32 , # 06:00-11:00
442+ 33 ,
443+ 34 ,
444+ 34 ,
445+ 33 ,
446+ 31 ,
447+ 29 , # 12:00-17:00
448+ 27 ,
449+ 25 ,
450+ 23 ,
451+ 21 ,
452+ 20 ,
453+ 19 ,
454+ 18 , # 18:00-24:00
377455 ]
378456 readings = make_readings_from_hourly_temps (base_time , hourly_temps )
379457
@@ -387,10 +465,31 @@ def test_summer_day_france(self, base_time):
387465 def test_spring_transition_day (self , base_time ):
388466 """Spring day with temperature crossing base multiple times."""
389467 hourly_temps = [
390- 12 , 11 , 10 , 10 , 11 , 12 , # 00:00-05:00 (below base)
391- 14 , 16 , 18 , 20 , 21 , 22 , # 06:00-11:00 (crossing base)
392- 23 , 23 , 22 , 21 , 19 , 17 , # 12:00-17:00 (above then crossing)
393- 15 , 14 , 13 , 12 , 12 , 12 , 12 # 18:00-24:00 (below base)
468+ 12 ,
469+ 11 ,
470+ 10 ,
471+ 10 ,
472+ 11 ,
473+ 12 , # 00:00-05:00 (below base)
474+ 14 ,
475+ 16 ,
476+ 18 ,
477+ 20 ,
478+ 21 ,
479+ 22 , # 06:00-11:00 (crossing base)
480+ 23 ,
481+ 23 ,
482+ 22 ,
483+ 21 ,
484+ 19 ,
485+ 17 , # 12:00-17:00 (above then crossing)
486+ 15 ,
487+ 14 ,
488+ 13 ,
489+ 12 ,
490+ 12 ,
491+ 12 ,
492+ 12 , # 18:00-24:00 (below base)
394493 ]
395494 readings = make_readings_from_hourly_temps (base_time , hourly_temps )
396495
0 commit comments