Source code for contrib.misc._timestamp

# -*- coding: utf-8 -*-
#
# badidatetime/_timestamp.py
#

import math
from datetime import datetime, timezone, timedelta


[docs] class TimestampUtils:
[docs] def solar_declination(self, day_of_year): """ Return solar declination (radians) using approximate formula. """ return math.radians(23.44) * math.sin(math.radians( 360 / 365 * (day_of_year - 81)))
[docs] def equation_of_time(self, day_of_year): """ Return the equation of time (minutes). """ B = math.radians(360 / 365 * (day_of_year - 81)) return 9.87 * math.sin(2 * B) - 7.53 * math.cos(B) - 1.5 * math.sin(B)
[docs] def solar_events(self, timestamp, latitude, longitude): """ Calculate solar noon, sunrise, and sunset for the given timestamp and coordinates. All results are UTC datetimes. Args: timestamp: POSIX timestamp (seconds since epoch) latitude: latitude in decimal degrees (positive north) longitude: longitude in decimal degrees (positive east, negative west) Returns: dict with keys: 'solar_noon', 'sunrise', 'sunset' (UTC datetimes) """ # Convert timestamp to date (UTC) dt = datetime.fromtimestamp(timestamp, tz=timezone.utc) n = dt.timetuple().tm_yday decl = self.solar_declination(n) # Equation of time (minutes) eqt = self.equation_of_time(n) # Solar noon (minutes from UTC midnight) solar_noon_min = 720 - 4 * longitude - eqt # Hour angle for sunrise/sunset (degrees) lat_r = math.radians(latitude) decl_r = decl try: h0 = math.degrees(math.acos( (math.sin(math.radians(-0.833)) - math.sin(lat_r) * math.sin( decl_r)) / (math.cos(lat_r) * math.cos(decl_r)) )) except ValueError: # Sun never rises or never sets (polar regions) return {"solar_noon": None, "sunrise": None, "sunset": None} # Sunrise and sunset times (minutes from UTC midnight) sunrise_min = solar_noon_min - 4 * h0 sunset_min = solar_noon_min + 4 * h0 base_date = datetime(dt.year, dt.month, dt.day, tzinfo=timezone.utc) solar_noon = base_date + timedelta(minutes=solar_noon_min) sunrise = base_date + timedelta(minutes=sunrise_min) sunset = base_date + timedelta(minutes=sunset_min) return {"solar_noon": solar_noon, "sunrise": sunrise, "sunset": sunset}
[docs] def timestamp_at_sunset(self, date: tuple, latitude: float, longitude: float): ts = datetime(*date, tzinfo=timezone.utc).timestamp() events = self.solar_events(ts, latitude, longitude) sunset_utc = events["sunset"] # Get POSIX timestamp at sunset (UTC) return sunset_utc.timestamp()