From 1cf40f5b40991b6dc567f979f6bd69fc63807e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Deuchnord?= Date: Tue, 22 Feb 2022 19:10:29 +0100 Subject: [PATCH] fix: prevent `get_ephemerides()` from returning values out of the dates given in arguments --- kosmorrolib/dateutil.py | 4 +- kosmorrolib/ephemerides.py | 118 ++++++++++++++++++++++++------------- 2 files changed, 79 insertions(+), 43 deletions(-) diff --git a/kosmorrolib/dateutil.py b/kosmorrolib/dateutil.py index 20bc3e5..6d0c96a 100644 --- a/kosmorrolib/dateutil.py +++ b/kosmorrolib/dateutil.py @@ -56,7 +56,9 @@ def normalize_datetime(date: datetime) -> datetime: datetime.datetime(2022, 1, 1, 0, 0) """ - new_date = datetime(date.year, date.month, date.day, date.hour, date.minute) + new_date = datetime( + date.year, date.month, date.day, date.hour, date.minute + ).replace(microsecond=0) if date.second >= 30: new_date += timedelta(minutes=1) diff --git a/kosmorrolib/ephemerides.py b/kosmorrolib/ephemerides.py index 0b51683..f12943b 100644 --- a/kosmorrolib/ephemerides.py +++ b/kosmorrolib/ephemerides.py @@ -152,15 +152,15 @@ def get_ephemerides( >>> get_ephemerides(Position(36.6794, 4.8555), date(2022, 7, 7), timezone=2) [>, - >, + >, >, >, - >, - >, + >, + >, >, - >, - >, - >] + >, + >, + >] Objects may not rise or set on the given date (e.g. they rise the previous day or set the next day). @@ -171,26 +171,64 @@ def get_ephemerides( >>> north_pole = Position(70, 20) >>> south_pole = Position(-70, 20) >>> get_ephemerides(north_pole, date(2021, 6, 20)) - [>, >, >, >, >, >, >, >, >, >] + [>, + >, + >, + >, + >, + >, + >, + >, + >, + >] >>> get_ephemerides(north_pole, date(2021, 12, 21)) - [>, >, >, >, >, >, >, >, >, >] + [>, + >, + >, + >, + >, + >, + >, + >, + >, + >] >>> get_ephemerides(south_pole, date(2021, 6, 20)) - [>, >, >, >, >, >, >, >, >, >] + [>, + >, + >, + >, + >, + >, + >, + >, + >, + >] >>> get_ephemerides(south_pole, date(2021, 12, 22)) - [>, >, >, >, >, >, >, >, >, >] - - Note that the ephemerides can only be computed for a date range. - Asking for the ephemerides with an out of range date will result in an exception: - - >>> get_ephemerides(Position(50.5824, 3.0624), date(1000, 1, 1)) - Traceback (most recent call last): - ... - kosmorrolib.exceptions.OutOfRangeDateError: The date must be between 1899-07-29 and 2053-10-07 + [>, + >, + >, + >, + >, + >, + >, + >, + >, + >] + + Please note: + - The ephemerides can only be computed for a date range. Asking for the ephemerides with an out of range date will result in an exception: + + >>> get_ephemerides(Position(50.5824, 3.0624), date(1000, 1, 1)) + Traceback (most recent call last): + ... + kosmorrolib.exceptions.OutOfRangeDateError: The date must be between 1899-07-29 and 2053-10-07 + + - The date given in parameter is considered as being given from the point of view of the given timezone. + Using a timezone that does not correspond to the place's actual one can impact the returned times. """ - ephemerides = [] def get_angle(for_aster: Object): def fun(time: Time) -> float: @@ -213,13 +251,19 @@ def get_ephemerides( fun.rough_period = 0.5 return fun + # The date given in argument is supposed to be given in the given timezone (more natural for a human), + # but we need it in UTC. Subtracting the timezone to get it in UTC. + start_time = get_timescale().utc( - for_date.year, for_date.month, for_date.day, timezone + for_date.year, for_date.month, for_date.day, -timezone ) + end_time = get_timescale().utc( - for_date.year, for_date.month, for_date.day, 23 + timezone, 59, 59 + for_date.year, for_date.month, for_date.day + 1, -timezone ) + ephemerides = [] + try: for aster in ASTERS: times, risen_info = find_discrete(start_time, end_time, is_risen(aster)) @@ -230,37 +274,27 @@ def get_ephemerides( culmination_time[0] if len(culmination_time) == 1 else None ) - if len(times) > 0: - rise_time = times[0] if risen_info[0] else None - set_time = times[0] if not risen_info[0] else None + for i, time in enumerate(times): + time_dt = normalize_datetime( + translate_to_timezone(time.utc_datetime(), to_tz=timezone) + ) - if len(times) == 2: - rise_time = times[0 if risen_info[0] else 1] - set_time = times[1 if not risen_info[1] else 0] + if time_dt is not None and time_dt.day != for_date.day: + continue - # Convert the Time instances to Python datetime objects - if rise_time is not None: - rise_time = normalize_datetime( - translate_to_timezone( - rise_time.utc_datetime().replace(microsecond=0), to_tz=timezone - ) - ) + if risen_info[i]: + rise_time = time_dt + else: + set_time = time_dt if culmination_time is not None: culmination_time = normalize_datetime( translate_to_timezone( - culmination_time.utc_datetime().replace(microsecond=0), + culmination_time.utc_datetime(), to_tz=timezone, ) ) - if set_time is not None: - set_time = normalize_datetime( - translate_to_timezone( - set_time.utc_datetime().replace(microsecond=0), to_tz=timezone - ) - ) - ephemerides.append( AsterEphemerides(rise_time, culmination_time, set_time, aster=aster) )