pydae 0.57__py3-none-any.whl → 0.57.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pydae/__init__.py +1 -1
- pydae/utils/dates.py +107 -6
- {pydae-0.57.dist-info → pydae-0.57.2.dist-info}/METADATA +1 -1
- {pydae-0.57.dist-info → pydae-0.57.2.dist-info}/RECORD +7 -7
- {pydae-0.57.dist-info → pydae-0.57.2.dist-info}/WHEEL +0 -0
- {pydae-0.57.dist-info → pydae-0.57.2.dist-info}/licenses/COPYING +0 -0
- {pydae-0.57.dist-info → pydae-0.57.2.dist-info}/licenses/LICENSE +0 -0
pydae/__init__.py
CHANGED
pydae/utils/dates.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import pytz
|
|
3
|
-
from typing import Optional,List
|
|
3
|
+
from typing import Optional,List,Tuple
|
|
4
4
|
|
|
5
5
|
def get_absolute_hour_of_year_with_dst(month: int, day: int, day_hour: int, year: int, timezone_name: str) -> int:
|
|
6
6
|
"""
|
|
@@ -205,20 +205,121 @@ def list_full_hours_between(start_dt: datetime, end_dt: datetime) -> List[dateti
|
|
|
205
205
|
|
|
206
206
|
return hours_list
|
|
207
207
|
|
|
208
|
-
def absolute_hours_list(
|
|
209
|
-
|
|
210
|
-
result_ini = parse_datetime( '1/12/2024 23:00', 'Europe/Paris')
|
|
211
|
-
result_end = parse_datetime('31/12/2024 23:00', 'Europe/Paris')
|
|
208
|
+
def absolute_hours_list(date_ini,date_end,time_zone='Europe/Paris'):
|
|
212
209
|
|
|
210
|
+
result_ini = parse_datetime(date_ini, time_zone)
|
|
211
|
+
result_end = parse_datetime(date_end, time_zone)
|
|
213
212
|
|
|
214
213
|
hours_list = []
|
|
215
214
|
for item in list_full_hours_between(result_ini,result_end):
|
|
216
215
|
hours_list += [datetime_to_hour_of_year(item)]
|
|
217
216
|
|
|
218
217
|
return hours_list
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def hour_index_to_date_components(absolute_hour_index: int, timezone_name: str) -> Optional[Tuple[int, int]]:
|
|
222
|
+
"""
|
|
223
|
+
Converts an absolute hour of the year index (0-indexed) to the corresponding
|
|
224
|
+
day of the year and hour of the day, respecting DST rules.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
absolute_hour_index: The 0-indexed hour of the year (e.g., 8759 is the last hour).
|
|
228
|
+
timezone_name: The IANA time zone string (e.g., 'Europe/Madrid').
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
A tuple (day_of_year, hour_of_day) as integers, or None on error.
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
current_year = datetime.datetime.now().year # Use the current year for the calculation
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
# 1. Define the time zone
|
|
238
|
+
tz = pytz.timezone(timezone_name)
|
|
239
|
+
|
|
240
|
+
# 2. Create the start-of-year time (Jan 1st, 00:00)
|
|
241
|
+
# This is the reference point for hour index 0.
|
|
242
|
+
start_of_year_naive = datetime.datetime(current_year, 1, 1, 0, 0, 0)
|
|
243
|
+
|
|
244
|
+
# Localize the start of the year to make it aware
|
|
245
|
+
start_of_year_aware = tz.localize(start_of_year_naive)
|
|
246
|
+
|
|
247
|
+
# 3. Create the time difference
|
|
248
|
+
# Multiplying the hour index by 3600 gives the exact number of seconds
|
|
249
|
+
# that have elapsed since the start_of_year_aware.
|
|
250
|
+
time_difference = datetime.timedelta(hours=absolute_hour_index)
|
|
251
|
+
|
|
252
|
+
# 4. Calculate the target time
|
|
253
|
+
# This addition operation correctly handles DST shifts. If 25 hours have
|
|
254
|
+
# passed since Jan 1st, and one hour was lost due to DST, the target time
|
|
255
|
+
# will only be advanced by 24 clock hours.
|
|
256
|
+
target_time_aware = start_of_year_aware + time_difference
|
|
257
|
+
|
|
258
|
+
# 5. Extract the required components
|
|
259
|
+
# %j gives the 1-indexed day of the year (1-366).
|
|
260
|
+
day_of_year = int(target_time_aware.strftime('%j'))
|
|
261
|
+
hour_of_day = target_time_aware.hour # 0-23
|
|
262
|
+
|
|
263
|
+
return (day_of_year, hour_of_day)
|
|
264
|
+
|
|
265
|
+
except pytz.exceptions.UnknownTimeZoneError:
|
|
266
|
+
print(f"Error: Timezone '{timezone_name}' is not recognized.")
|
|
267
|
+
return None
|
|
268
|
+
except Exception as e:
|
|
269
|
+
print(f"An unexpected error occurred: {e}")
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def day_to_absolute_hour(day_of_year: int, target_year: int, timezone_name: str = 'Europe/Madrid') -> int:
|
|
274
|
+
"""
|
|
275
|
+
Calculates the absolute hour of the year (based on UTC) for a specific day
|
|
276
|
+
at 00:00 local time, correctly accounting for time zone and DST changes.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
day_of_year: The sequential day of the year (1 for Jan 1st, 365/366 for Dec 31st).
|
|
280
|
+
target_year: The year for the calculation (e.g., 2024).
|
|
281
|
+
timezone_name: The target time zone string (e.g., 'Europe/London', 'America/New_York').
|
|
282
|
+
Defaults to 'UTC'.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
The total number of hours elapsed from the beginning of the year
|
|
286
|
+
(Jan 1st 00:00 UTC) up to the specified date and time (converted to UTC).
|
|
287
|
+
|
|
288
|
+
Raises:
|
|
289
|
+
pytz.UnknownTimeZoneError: If the provided timezone_name is invalid.
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
# 1. Define the start of the year and the target date (unlocalized)
|
|
293
|
+
start_of_year = datetime.datetime(target_year, 1, 1, 0, 0, 0)
|
|
294
|
+
|
|
295
|
+
# Calculate the target date (00:00 local time)
|
|
296
|
+
# We subtract 1 from day_of_year because Jan 1st is day 1, but represents 0 days of offset.
|
|
297
|
+
target_date = start_of_year + datetime.timedelta(days=day_of_year - 1)
|
|
298
|
+
|
|
299
|
+
try:
|
|
300
|
+
# 2. Localize the dates
|
|
301
|
+
tz = pytz.timezone(timezone_name)
|
|
219
302
|
|
|
303
|
+
# Localize the date to the target timezone (this handles DST shift at 00:00 if any)
|
|
304
|
+
# .localize() is the safe way to assign timezone awareness.
|
|
305
|
+
start_of_year_local = tz.localize(start_of_year)
|
|
306
|
+
target_date_local = tz.localize(target_date)
|
|
307
|
+
|
|
308
|
+
# 3. Convert both localized times to UTC
|
|
309
|
+
start_of_year_utc = start_of_year_local.astimezone(pytz.utc)
|
|
310
|
+
target_date_utc = target_date_local.astimezone(pytz.utc)
|
|
220
311
|
|
|
312
|
+
# 4. Calculate the difference in hours
|
|
313
|
+
time_difference = target_date_utc - start_of_year_utc
|
|
314
|
+
|
|
315
|
+
# Convert total seconds in the timedelta to total hours (integer result)
|
|
316
|
+
absolute_hour = int(time_difference.total_seconds() / 3600)
|
|
317
|
+
|
|
318
|
+
return absolute_hour
|
|
221
319
|
|
|
320
|
+
except pytz.UnknownTimeZoneError:
|
|
321
|
+
raise pytz.UnknownTimeZoneError(f"Time zone '{timezone_name}' is not recognized by pytz.")
|
|
322
|
+
|
|
222
323
|
if __name__ == '__main__':
|
|
223
324
|
|
|
224
325
|
result_1 = parse_datetime('31/12/2024 23:00', 'Europe/Paris')
|
|
@@ -229,5 +330,5 @@ if __name__ == '__main__':
|
|
|
229
330
|
|
|
230
331
|
print(list_full_hours_between(result_ini,result_end))
|
|
231
332
|
|
|
232
|
-
print(absolute_hours_list('1/
|
|
333
|
+
print(absolute_hours_list('1/1/2024 00:00','31/1/2024 23:00'))
|
|
233
334
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
pydae/.gitignore,sha256=c1jUQV9WXX3PWrlOzHiKvUWFomLJUrfYogbU7nYwAwc,288
|
|
2
|
-
pydae/__init__.py,sha256=
|
|
2
|
+
pydae/__init__.py,sha256=fUy1IioPTAmI5CGTEuu5wHj1YqgbZ1bjvpvdZA2X7eM,106
|
|
3
3
|
pydae/b_pu.py,sha256=FdRRVieJLQDYPwYNWhbXJ0SXvf4jtPdbvIZTKWi16I0,6775
|
|
4
4
|
pydae/bpu.py,sha256=FdRRVieJLQDYPwYNWhbXJ0SXvf4jtPdbvIZTKWi16I0,6775
|
|
5
5
|
pydae/build.py,sha256=ECfc_doyK9PhrjEAlWJGLfirQmpT24XuYNxUgtrXI74,46151
|
|
@@ -735,15 +735,15 @@ pydae/urisi/vsgs/vsg_lpf_ib.hjson,sha256=xpuo5fPCdO5Ze0X-KDCsa_eRpde5f5KDDFoDkWI
|
|
|
735
735
|
pydae/urisi/vsgs/vsgs.py,sha256=v17sLm7EaaAyBVJk9-8DnLtxPDtXmkyizFlGhgqyFEE,644
|
|
736
736
|
pydae/urisi/vsgs/xy_0.json,sha256=Q6qWPIqEP-w5Qu2twd3S4PX4zMggpNpG2W62e7ry70g,851
|
|
737
737
|
pydae/utils/__init__.py,sha256=kwp76qeU2mnwrCexDSF15id9ih12Q0VRL3l-_c6omcQ,184
|
|
738
|
-
pydae/utils/dates.py,sha256=
|
|
738
|
+
pydae/utils/dates.py,sha256=bx3NyCkyWFbp3hlsOTbUSXSbXDAqYGIWA8aXoslE0_I,13612
|
|
739
739
|
pydae/utils/ss_num2sym.py,sha256=ZA-x01y1mEWk1HdlpNv9rNspFdH0RBlTq_JRDHmjlpU,3209
|
|
740
740
|
pydae/utils/svg2pdf.py,sha256=6tNORhlu_cMPDp264Kg3X_eBORfT9Q1cqAcWaWgDs7k,1861
|
|
741
741
|
pydae/utils/tools.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
742
742
|
pydae/utils/types_converter.py,sha256=3eAWwELgG1d6iFX8sn8iGPIp6NBaX4I-eyUriRDOFyE,7929
|
|
743
743
|
pydae/utils/utils.py,sha256=AI0wZr4PJ3Td3vjfAW06FJdgcK01TpUAukhG37gZP5g,1079
|
|
744
744
|
pydae/utils/emtp/readPL4.py,sha256=R59KhXTmFrqtdv-9nv5tkdHoTs9uoofGqEfBCF4fGEY,3088
|
|
745
|
-
pydae-0.57.dist-info/licenses/COPYING,sha256=QWnWoslbTjQmtlFSRoGF3wxJEJuTJdlEMZ7lHtbGAeQ,1139
|
|
746
|
-
pydae-0.57.dist-info/licenses/LICENSE,sha256=8hQe1oM4ySdliF3R-NEvR6HqrcGDKvsLFJC3gA1sNjY,1108
|
|
747
|
-
pydae-0.57.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
748
|
-
pydae-0.57.dist-info/METADATA,sha256=
|
|
749
|
-
pydae-0.57.dist-info/RECORD,,
|
|
745
|
+
pydae-0.57.2.dist-info/licenses/COPYING,sha256=QWnWoslbTjQmtlFSRoGF3wxJEJuTJdlEMZ7lHtbGAeQ,1139
|
|
746
|
+
pydae-0.57.2.dist-info/licenses/LICENSE,sha256=8hQe1oM4ySdliF3R-NEvR6HqrcGDKvsLFJC3gA1sNjY,1108
|
|
747
|
+
pydae-0.57.2.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
748
|
+
pydae-0.57.2.dist-info/METADATA,sha256=pPD7BWSoPod5OcSfSLQh_E3EJjDn3n8UynyO4l9reUM,1090
|
|
749
|
+
pydae-0.57.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|