He pasado bastante tiempo escribiendo esto:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from math import *
class RiseSet(object):
__ZENITH = {'official': 90.833,
'civil': '96',
'nautical': '102',
'astronomical': '108'}
def __init__(self, day, month, year, latitude, longitude, daylight=False,
elevation=840, zenith='official'):
''' elevation is set to 840 (m) because that is the mean height of land above the sea level '''
if abs(latitude) > 63.572375290155:
raise ValueError('Invalid latitude: {0}.'.format(latitude))
if zenith not in self.__ZENITH:
raise ValueError('Invalid zenith value, must be one of {0}.'.format
(self.__ZENITH.keys()))
self.day = day
self.month = month
self.year = year
self.latitude = latitude
self.longitude = longitude
self.daylight = daylight
self.elevation = elevation
self.zenith = zenith
def getZenith(self):
return cos(radians(self.__ZENITH[self.zenith]))
def dayOfTheYear(self):
n0 = floor(275*self.month/9)
n1 = floor((self.month + 9) / 12)
n2 = (1 + floor((self.year - 4*floor(self.year/4) + 2) / 3))
return n0 - (n1*n2) + self.day - 30
def approxTime(self):
sunrise = self.dayOfTheYear() + ((6 - (self.longitude/15.0)) / 24)
sunset = self.dayOfTheYear() + ((18 - (self.longitude/15.0)) / 24)
return (sunrise, sunset)
def sunMeanAnomaly(self):
sunrise = (0.9856 * self.approxTime()[0]) - 3.289
sunset = (0.9856 * self.approxTime()[1]) - 3.289
return (sunrise, sunset)
def sunTrueLongitude(self):
sma = self.sunMeanAnomaly()
sunrise = sma[0] + (1.916*sin(radians(sma[0]))) + \
(0.020*sin(radians(2*sma[0]))) + 282.634
if sunrise < 0:
sunrise += 360
if sunrise > 360:
sunrise -= 360
sunset = sma[1] + (1.916*sin(radians(sma[1]))) + \
(0.020*sin(radians(2*sma[1]))) + 282.634
if sunset <= 0:
sunset += 360
if sunset > 360:
sunset -= 360
return (sunrise, sunset)
def sunRightAscension(self):
stl = self.sunTrueLongitude()
sunrise = atan(radians(0.91764*tan(radians(stl[0]))))
if sunrise <= 0:
sunrise += 360
if sunrise > 360:
sunrise -= 360
sunset = atan(radians(0.91764*tan(radians(stl[1]))))
if sunset <= 0:
sunset += 360
if sunset > 360:
sunset -= 360
sunrise_stl_q = (floor(stl[0]/90)) * 90
sunrise_ra_q = (floor(sunrise/90)) * 90
sunrise = sunrise + (sunrise_stl_q - sunrise_ra_q)
sunrise = sunrise/15.0
sunset_stl_q = (floor(stl[1]/90)) * 90
sunset_ra_q = (floor(sunset/90)) * 90
sunset = sunrise + (sunset_stl_q - sunset_ra_q)
sunset /= 15.0
return (sunrise, sunset)
def sunDeclination(self):
sunrise_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[0]))
sunrise_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))
sunset_sin_dec = 0.39782 * sin(radians(self.sunTrueLongitude()[1]))
sunset_cos_dec = cos(radians(asin(radians(sunrise_sin_dec))))
return (sunrise_sin_dec, sunrise_cos_dec,
sunset_sin_dec, sunset_cos_dec)
def sunHourAngle(self):
sd = self.sunDeclination()
sunrise_cos_h = (cos(radians(self.getZenith())) - (sd[0]* \
sin(radians(self.latitude))) / (sd[1]* \
cos(radians(self.latitude))))
if sunrise_cos_h > 1:
raise Exception('The sun never rises on this location.')
sunset_cos_h = (cos(radians(self.getZenith())) - (sd[2]* \
sin(radians(self.latitude))) / (sd[3]* \
cos(radians(self.latitude))))
if sunset_cos_h < -1:
raise Exception('The sun never sets on this location.')
sunrise = 360 - acos(radians(sunrise_cos_h))
sunrise /= 15.0
sunset = acos(radians(sunrise_cos_h))
sunset /= 15.0
return (sunrise, sunset)
def localMeanTime(self):
sunrise = self.sunHourAngle()[0] + self.sunRightAscension()[0] - \
(0.06571*self.approxTime()[0]) - 6.622
sunset = self.sunHourAngle()[1] + self.sunRightAscension()[1] - \
(0.06571*self.approxTime()[1]) - 6.622
return (sunrise, sunset)
def convertToUTC(self):
sunrise = self.localMeanTime()[0] - (self.longitude/15.0)
if sunrise <= 0:
sunrise += 24
if sunrise > 24:
sunrise -= 24
sunset = self.localMeanTime()[1] - (self.longitude/15.0)
if sunset <= 0:
sunset += 24
if sunset > 24:
sunset -= 24
return (sunrise, sunset)
def __str__(self):
return None
Ahora todavía no es funcional (arruiné algunos cálculos). Volveré a ello más tarde (si todavía tengo el coraje) para completarlo / comentarlo .
Además, algunos recursos interesantes que encontré mientras investigaba el tema: