1414
1515"""
1616
17- from datetime import datetime
17+ from datetime import datetime , timedelta , timezone
1818from zoneinfo import ZoneInfo
1919
2020import swisseph as swe
@@ -29,37 +29,39 @@ def ambiguous(dt: datetime) -> bool:
2929 return tz .datetime_ambiguous (dt )
3030
3131
32- def timezone (lat : float , lon : float ) -> str :
32+ def timezone_name (lat : float , lon : float ) -> str :
3333 """ Returns a timezone string based on decimal lat/lon coordinates. """
3434 return TimezoneFinder ().timezone_at (lat = lat , lng = lon )
3535
3636
37- def localize (dt : datetime , lat : float , lon : float , is_dst : bool = None ) -> datetime :
38- """ Localizes a naive datetime based on decimal lat/lon coordinates. """
39- return dt .replace (tzinfo = ZoneInfo (timezone (lat , lon )), fold = 1 if is_dst is False else 0 )
37+ def localize (dt : datetime , lat : float , lon : float , offset : float = None , is_dst : bool = None ) -> datetime :
38+ """ Localizes a naive datetime based on either decimal lat/lon
39+ coordinates or an explicit UTC offset. """
40+ zone = ZoneInfo (timezone_name (lat , lon )) if offset is None else timezone (timedelta (hours = offset ))
41+ return dt .replace (tzinfo = zone , fold = 1 if is_dst is False else 0 )
4042
4143
42- def to_datetime (dt : str | float | datetime , lat : float = None , lon : float = None , is_dst : bool = None ) -> datetime :
44+ def to_datetime (dt : str | float | datetime , lat : float = None , lon : float = None , offset : float = None , is_dst : bool = None ) -> datetime :
4345 """ Convert an unknown into a datetime. Unknowns can be either an
4446 ISO-formatted string, a Julian Date, or already a datetime. """
4547 no_coords = lat is None or lon is None
4648 if isinstance (dt , str ):
4749 date_time = datetime .fromisoformat (dt )
48- return date_time .replace (tzinfo = ZoneInfo ('UTC' )) if no_coords else localize (date_time , lat , lon , is_dst )
50+ return date_time .replace (tzinfo = ZoneInfo ('UTC' )) if no_coords else localize (date_time , lat , lon , offset , is_dst )
4951 if isinstance (dt , float ):
5052 ut = swe .revjul (dt )
5153 time = convert .dec_to_dms (ut [3 ])[1 :]
5254 date_time = datetime (* ut [:3 ], * time , tzinfo = ZoneInfo ('UTC' ))
53- return date_time if no_coords else date_time .astimezone (ZoneInfo (timezone (lat , lon )))
55+ return date_time if no_coords else date_time .astimezone (ZoneInfo (timezone_name (lat , lon )))
5456 if isinstance (dt , datetime ):
5557 if no_coords :
5658 return dt .replace (tzinfo = ZoneInfo ('UTC' )) if dt .tzinfo is None else dt
5759 else :
58- return localize (dt , lat , lon , is_dst )
60+ return localize (dt , lat , lon , offset , is_dst )
5961 return None
6062
6163
62- def to_jd (dt : str | float | datetime , lat : float = None , lon : float = None , is_dst : bool = None ) -> float :
64+ def to_jd (dt : str | float | datetime , lat : float = None , lon : float = None , offset : float = None , is_dst : bool = None ) -> float :
6365 """ Convert an unknown into a Julian date. Unknowns can be either an
6466 ISO-formatted string, already a Julian Date, or a datetime. """
6567 if isinstance (dt , float ):
@@ -72,7 +74,7 @@ def to_jd(dt: str | float | datetime, lat: float = None, lon: float = None, is_d
7274 return None
7375
7476 if lat is not None and lon is not None :
75- date_time = localize (date_time , lat , lon , is_dst )
77+ date_time = localize (date_time , lat , lon , offset , is_dst )
7678 elif date_time .tzinfo is None :
7779 date_time = date_time .replace (tzinfo = ZoneInfo ('UTC' ))
7880
0 commit comments