# Sunrise and sunset [closed]

I'm a bit of a romantic, I love taking my wife out to see the sunrises and sunsets in the place we are located. For the sake of this exercise let's say I don't have code that can tell me the time of either sunset or sunrise for whatever date, latitude and longitude I would happen to be in.

Your task, coders, is to generate the smallest code possible that takes a decimal latitude and longitude (taken in degrees N and W, so degrees S and E will be taken as negatives) and a date in the format YYYY-MM-DD (from Jan 1, 2000 onwards) and it will spit out two times in 24hr format for the sunrise and sunset.

e.g. For today in Sydney, Australia

riseset -33.87 -151.2 2013-12-27

05:45 20:09


Bonuses: -100 if you can factor in elevation -100 if you can factor daylight savings

The code MUST spit out times in the relevant time zone specified in the input based off the latitude and longitude OR in the client machine's own time zone.

• Wait, what, we have to do a [latitude x longitude] => [timezone] lookup? Do we get a data file for that? Or a server we can access? Or is there a language that has such stuff built in? Can you tell us which one? Or we have to memorize the timezone boundaries? To what precision? Where do we get this data? Do you realize this data will take up most of the code length? What about coordinates that fall exactly on the timezone boundary? Say, the geographic poles? Also, what behavior is allowed when the input is a polar region during a polar night / day? What about out-of-range coordinates? Dec 26, 2013 at 22:11
• I would love the challenge to calculate the horizon based on a point above an idealised sphere, but I hate the associated challenge to find, hand-compress, programatically decopmress and then look up in, a timezone lookup map. Unless, of course, we can use idealized timezones (the offset is chosen so that the sun is the highest during noon, then it is rounded to the nearest hour) as well. Dec 26, 2013 at 22:23
• @JanDvorak Use whatever you can, if the language you use can exploit the client's time zone then by all means do so... Dec 26, 2013 at 23:20
• What is the desired behavior for polar regions when it's a polar day/night? Dec 27, 2013 at 7:44
• Here is a tool that does exactly the same: weatherimages.org/latlonsun.html Dec 29, 2013 at 10:01

I've spent quite some time writing this:

#!/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):

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]))) + \

if sunrise < 0:
sunrise += 360
if sunrise > 360:
sunrise -= 360

sunset = sma[1] + (1.916*sin(radians(sma[1]))) + \

if sunset <= 0:
sunset += 360
if sunset > 360:
sunset -= 360

return (sunrise, sunset)

def sunRightAscension(self):
stl = self.sunTrueLongitude()

if sunrise <= 0:
sunrise += 360
if sunrise > 360:
sunrise -= 360

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):

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]* \
if sunrise_cos_h > 1:
raise Exception('The sun never rises on this location.')

sunset_cos_h = (cos(radians(self.getZenith())) - (sd[2]* \
if sunset_cos_h < -1:
raise Exception('The sun never sets on this location.')

sunrise /= 15.0

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


Now it's not yet functional (I screwed up some calculations) - I'll come back to it later (if I'll still have the courage) to complete it / comment it.

Also, some interesting resources that I found while researching the subject:

• I just saw your comment of # It's late, I'm tired, and OP is a prick for asking me to do this. There was no obligation to do this task... Please don't put comments like this in your code... It does not sit favorably with other coders... including me. I admire the fact that you gave it a red hot go, and the other links you've provided, but please do not use comments like this ever again... Jan 3, 2014 at 10:01
• @Eliseod'Annunzio You have my apologies. Jan 3, 2014 at 12:16
• @Eliseod'Annunzio I did not intend to offend you. I would also like to thank you for giving me an absolutely fantastic idea to research and code. Now I want to turn this into a self-standing python module (with sys arguments and so on). It turns out to be a little more complicated than I previously thought, but I intend to pull this off. Thank you again. Jan 3, 2014 at 12:26
• @Alex, do you realize this challenge is a year old? I'm pretty sure he won. Jan 28, 2015 at 20:52
• @mbomb007: Didn't realize. Jan 28, 2015 at 20:54