diff --git a/kosmorrolib/enum.py b/kosmorrolib/enum.py
index e9420cd..b4438e9 100644
--- a/kosmorrolib/enum.py
+++ b/kosmorrolib/enum.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-from enum import Enum, auto
+from enum import Enum
class MoonPhaseType(Enum):
@@ -16,6 +16,13 @@ class MoonPhaseType(Enum):
WANING_CRESCENT = 8
+class SeasonType(Enum):
+ MARCH_EQUINOX = 0
+ JUNE_SOLSTICE = 1
+ SEPTEMBER_EQUINOX = 2
+ DECEMBER_SOLSTICE = 3
+
+
class EventType(Enum):
"""An enumeration for the supported event types."""
@@ -25,6 +32,7 @@ class EventType(Enum):
MAXIMAL_ELONGATION = 4
MOON_PERIGEE = 5
MOON_APOGEE = 6
+ SEASON_CHANGE = 7
class ObjectType(Enum):
diff --git a/kosmorrolib/events.py b/kosmorrolib/events.py
index 20d5d03..a0bcee8 100644
--- a/kosmorrolib/events.py
+++ b/kosmorrolib/events.py
@@ -5,16 +5,34 @@ from datetime import date
from skyfield.errors import EphemerisRangeError
from skyfield.timelib import Time
from skyfield.searchlib import find_discrete, find_maxima, find_minima
+from skyfield import almanac
from numpy import pi
-from .model import Event, Star, Planet, ASTERS
-from .dateutil import translate_to_timezone
-from .enum import EventType, ObjectIdentifier
-from .exceptions import OutOfRangeDateError
-from .core import get_timescale, get_skf_objects, flatten_list
+from kosmorrolib.model import Event, Star, Planet, ASTERS
+from kosmorrolib.dateutil import translate_to_timezone
+from kosmorrolib.enum import EventType, ObjectIdentifier, SeasonType
+from kosmorrolib.exceptions import OutOfRangeDateError
+from kosmorrolib.core import get_timescale, get_skf_objects, flatten_list
def _search_conjunction(start_time: Time, end_time: Time, timezone: int) -> [Event]:
+ """Function to search conjunction.
+
+ **Warning:** this is an internal function, not intended for use by end-developers.
+
+ Will return MOON and VENUS opposition on 2021-06-12:
+
+ >>> conjunction = _search_conjunction(get_timescale().utc(2021,6,12),get_timescale().utc(2021,6,13),0)
+ >>> len(conjunction)
+ 1
+ >>> conjunction[0].objects
+ [, ]
+
+ Will return nothing if no conjunction happens:
+
+ >>> _search_conjunction(get_timescale().utc(2021,6,17),get_timescale().utc(2021,6,18),0)
+ []
+ """
earth = get_skf_objects()["earth"]
aster1 = None
aster2 = None
@@ -177,13 +195,13 @@ def _search_maximal_elongations(
)
for i, time in enumerate(times):
- elongation = elongations[i]
+ elongation = round(elongations[i], 1)
events.append(
Event(
EventType.MAXIMAL_ELONGATION,
[aster],
translate_to_timezone(time.utc_datetime(), timezone),
- details="{:.3n}°".format(elongation),
+ details={"deg": elongation},
)
)
@@ -245,6 +263,45 @@ def _search_moon_perigee(start_time: Time, end_time: Time, timezone: int) -> [Ev
return events
+def _search_earth_season_change(
+ start_time: Time, end_time: Time, timezone: int
+) -> [Event]:
+ """Function to find earth season change event.
+
+ **Warning:** this is an internal function, not intended for use by end-developers.
+
+ Will return JUNE SOLSTICE on 2020/06/20:
+
+ >>> season_change = _search_earth_season_change(get_timescale().utc(2020, 6, 20), get_timescale().utc(2020, 6, 21), 0)
+ >>> len(season_change)
+ 1
+ >>> season_change[0].event_type
+
+ >>> season_change[0].details
+ {'season': }
+
+ Will return nothing if there is no season change event in the period of time being calculated:
+
+ >>> _search_earth_season_change(get_timescale().utc(2021, 6, 17), get_timescale().utc(2021, 6, 18), 0)
+ []
+ """
+ events = []
+ event_time, event_id = almanac.find_discrete(
+ start_time, end_time, almanac.seasons(get_skf_objects())
+ )
+ if len(event_time) == 0:
+ return []
+ events.append(
+ Event(
+ EventType.SEASON_CHANGE,
+ [],
+ translate_to_timezone(event_time.utc_datetime()[0], timezone),
+ details={"season": SeasonType(event_id[0])},
+ )
+ )
+ return events
+
+
def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
"""Calculate and return a list of events for the given date, adjusted to the given timezone if any.
@@ -265,7 +322,7 @@ def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
If there is no events for the given date, then an empty list is returned:
- >>> get_events(date(2021, 3, 20))
+ >>> get_events(date(2021, 4, 20))
[]
:param for_date: the date for which the events must be calculated
@@ -289,6 +346,7 @@ def get_events(for_date: date = date.today(), timezone: int = 0) -> [Event]:
_search_maximal_elongations,
_search_moon_apogee,
_search_moon_perigee,
+ _search_earth_season_change,
]:
found_events.append(fun(start_time, end_time, timezone))
diff --git a/kosmorrolib/model.py b/kosmorrolib/model.py
index 1f4a362..4a69147 100644
--- a/kosmorrolib/model.py
+++ b/kosmorrolib/model.py
@@ -154,7 +154,7 @@ class Event(Serializable):
objects: [Object],
start_time: datetime,
end_time: Union[datetime, None] = None,
- details: str = None,
+ details: {str: any} = None,
):
self.event_type = event_type
self.objects = objects
diff --git a/tests/events.py b/tests/events.py
index 70f12a7..0132692 100644
--- a/tests/events.py
+++ b/tests/events.py
@@ -74,7 +74,7 @@ EXPECTED_EVENTS = [
EventType.MAXIMAL_ELONGATION,
[ASTERS[2]],
datetime(2020, 2, 10, 13, 46),
- details="18.2°",
+ details={"deg": 18.2},
),
Event(EventType.MOON_PERIGEE, [ASTERS[1]], datetime(2020, 2, 10, 20, 34)),
],
@@ -86,14 +86,14 @@ EXPECTED_EVENTS = [
EventType.MAXIMAL_ELONGATION,
[ASTERS[2]],
datetime(2020, 3, 24, 1, 56),
- details="27.8°",
+ details={"deg": 27.8},
),
Event(EventType.MOON_APOGEE, [ASTERS[1]], datetime(2020, 3, 24, 15, 39)),
Event(
EventType.MAXIMAL_ELONGATION,
[ASTERS[3]],
datetime(2020, 3, 24, 21, 58),
- details="46.1°",
+ details={"deg": 46.1},
),
],
),