def elevations(self, days_offset=0): ''' Return the time of the astronomical, nautical, and civil dusk and dawns, as well as the solar noon and the sunrise and sunset, for the day (local time). @param days_offset:int The number of days into the future, 0 for today. @return :(:str?, :str?, :str?, :str?, :str, The time, restrict to the selected day of, in order: :str?, :str?, :str?, :str?) the astronomical dawn, the nautical dawn, the civil dawn, the sunrise, the solar noon, the sunset, the the civil dusk, thenautical dusk, and the astronomical dusk. (Those are in chronological order.) If such condition is not meet during the day, `None` is returned in place. Solar noon is guaranteed (I think.) Times are formatted in '%Y-%m-%d %H:%M:%S'. ''' import solar_python as s, time tz = -(time.timezone, time.altzone)[time.localtime().tm_isdst] a_day = 60 * 60 * 24 t = time.time() t += tz t -= t % a_day t -= tz t += days_offset * a_day start = s.epoch_to_julian_centuries(t) end = s.epoch_to_julian_centuries(t + a_day) t5a = s.future_elevation_derivative(self.lat, self.lon, 0, start) t5b = s.future_elevation_derivative(self.lat, self.lon, 0, t5a + 0.0000002) e1 = s.solar_elevation(self.lat, self.lon, t5a) e2 = s.solar_elevation(self.lat, self.lon, t5b) t5 = t5a if e1 > e2 else t5b t1 = s.past_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_ASTRONOMICAL_DUSK_DAWN, t5) t2 = s.past_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_NAUTICAL_DUSK_DAWN, t5) t3 = s.past_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_CIVIL_DUSK_DAWN, t5) t4 = s.past_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_SUNSET_SUNRISE, t5) t6 = s.future_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_SUNSET_SUNRISE, t5) t7 = s.future_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_CIVIL_DUSK_DAWN, t5) t8 = s.future_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_NAUTICAL_DUSK_DAWN, t5) t9 = s.future_elevation(self.lat, self.lon, s.SOLAR_ELEVATION_ASTRONOMICAL_DUSK_DAWN, t5) t = (t1, t2, t3, t4, t5, t6, t7, t8, t9) #return tuple(Solar.__jc_to_str(x) if x is not None and start <= x <= end else None for x in t) return tuple(Solar.__jc_to_str(x) for x in t)
def future_elevation(self, elevation): """ Predict the time point of the next time the Sun reaches a specific elevation @param elevation:float The elevation of interest @return :float? The calculated time point, in POSIX time, `None` if none were found within a year """ return self.u(solar_python.future_elevation(self.lat, self.lon, elevation, self.now()))
def future_elevation(self, elevation): ''' Predict the time point of the next time the Sun reaches a specific elevation @param elevation:float The elevation of interest @return :float? The calculated time point, in POSIX time, `None` if none were found within a year ''' return self.u( solar_python.future_elevation(self.lat, self.lon, elevation, self.now()))
def get_elev(elev, start, morning): end = start + 0.0099 while start < end: rc = sol.future_elevation(lat, lon, elev, start) if rc is None: return (None, end) else: start = rc + 1e-06 d = sol.solar_elevation(lat, lon, rc + 3e-09) d -= sol.solar_elevation(lat, lon, rc) if d >= 0 if morning else d <= 0: return (sol.julian_centuries_to_epoch(rc), start) return (None, end)
def hours(self, elevations, days_offset=0, format='%ih %i\' %i\'\''): ''' Calculates the time and duration when the Sun's elevation is in a specific range. We will call this the X hour. Both the morning X hour and evening X hour is calculated. These may in fact be the same. @param days_offset:int The number of days into the future, 0 for today @param :(float, float) The Sun's lowest (first element) and highest (second element) elevation during the X hour @param format:str? The format for the returned strings, must take three integers, in order: hours, minutes, and seconds, or `None` if the total seconds shall be returned as integers @param :(str?, str?, str|int, str?, str?, str|int) 0: The beginning of the morning X hour 1: The end of the morning X hour 2: The duration of the morning X hour 3: The beginning of the evening X hour 4: The end of the evening X hour 5: The duration of the evening X hour ''' # TODO support not adjusting the timezone import solar_python as s, time tz = -(time.timezone, time.altzone)[time.localtime().tm_isdst] a_day = 60 * 60 * 24 t = time.time() t += tz t -= t % a_day t -= tz t += days_offset * a_day start = s.epoch_to_julian_centuries(t) end = s.epoch_to_julian_centuries(t + a_day) t1 = s.future_elevation(self.lat, self.lon, elevations[0], start) t2 = s.future_elevation(self.lat, self.lon, elevations[1], start) t3 = s.past_elevation(self.lat, self.lon, elevations[1], end) t4 = s.past_elevation(self.lat, self.lon, elevations[0], end) (t1, t2, t3, t4) = tuple(x if x is not None and start <= x <= end else None for x in (t1, t2, t3, t4)) if t2 is None: t2 = t4 if t3 is None: t3 = t1 def dur(a, z): if a is None and z is None: e = s.solar_elevation(self.lat, self.lon, (start + end) / 2) if elevations[0] <= e <= elevations[1]: return s.julian_centuries_to_epoch( end) - s.julian_centuries_to_epoch(start) return 0 elif a is None and z is not None: return s.julian_centuries_to_epoch( z) - s.julian_centuries_to_epoch(start) elif a is not None and z is None: return s.julian_centuries_to_epoch( end) - s.julian_centuries_to_epoch(a) else: return s.julian_centuries_to_epoch( z) - s.julian_centuries_to_epoch(a) d12 = dur(t1, t2) d34 = dur(t3, t4) (t1, t2, t3, t4) = tuple( Solar.__jc_to_str(x) if x is not None else None for x in (t1, t2, t3, t4)) def strise(s): if format is None: return int(s) m, s = s // 60, s % 60 h, m = m // 60, m % 60 return format % (h, m, s) return (t1, t2, strise(d12), t3, t4, strise(d34))