Get sunrise and sunset time based on latitude and longitude

Question

• Hi. I've tried my best to find a correct forum for where I can post about the location-specific/time question, but here goes:

Home Automation software, like ActiveHome Pro and Insteon Timer Software (scroll down) have an ability to let me select a longitude/latitude (or city/state) based on sunrise and sunset time, so I wanted to implement this when developing my own home automation application.

Once I know my longitude and latitude (www.maporama.com is where I went there to find my longitude and latitude for my home address), how do I go about known when a sunrise and sunset occour at a certain time? I do believe that home automation applications don't connect to the Internet to get the times for sunrise/sunset for every day, as it doesn't use the Internet...

Sunday, July 15, 2007 7:43 PM

All replies

• If you're prepared to deal with the math involved, see http://www.srrb.noaa.gov/highlights/sunrise/calcdetails.html.  Otherwise there may be web services you could query for the data you want.
Sunday, July 15, 2007 7:53 PM
• You could also try looking at this project in C++, but it also mentions the same source as Peter (NOAA);

Sunday, July 15, 2007 8:58 PM
• I can handle math once I study more since I've completed beginning algebra in college of first semester of this year.

Thanks.

Monday, July 16, 2007 2:36 AM
• Boy I got a lot of clean-up to do, but I'll give myself a rest until today (it's after midnight).

In the meantime, here's my converted code (note that I omitted one function off since I don't care for DD-MONTH format but went with mm/dd/yyyy):

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace GraysonPeddie.HomeAutomation.Network.Server

{

public static class SolarPositionCalculator

{

{

return ( 180.0 * angleRadian / Math.PI );

}

public static double ConvertFromDegreesToRadian ( double angleDegrees )

{

return ( Math.PI * angleDegrees / 180.0 );

}

/// <summary>

/// Finds numerical day-of-year from month, day,

/// and leap year information.

/// </summary>

/// <param name="month">Month of year</param>

/// <param name="day">Day of month</param>

/// <param name="isLeapYear">Is the year a leap year?</param>

/// <returns>The numerical day of year</returns>

public static double CalculateDayOfYear

( int month , int day , bool isLeapYear )

{

int leapYear = isLeapYear ? 1 : 2;

return ( Math.Floor ( ( ( 275.0 * month ) / 9.0 ) - leapYear ) *

Math.Floor ( ( ( month + 9.0 ) / 12.0 ) + day - 30 ) );

}

/// <summary>

/// Derives weekday from Julian Day

/// </summary>

/// <param name="julianDay">Julian Day</param>

/// <returns>String containing name of weekday</returns>

public static string CalculateDayOfWeek ( double julianDay )

{

double day = ( julianDay + 1.5 ) % 7;

return

( day == 0 ) ?  "Sunday" :

( day == 1 ) ?  "Monday" :

( day == 2 ) ?  "Tuesday" :

( day == 3 ) ?  "Wednesday" :

( day == 4 ) ?  "Thursday" :

( day == 5 ) ?  "Friday" :

"Saturday";

}

/// <summary>

/// Julian Day from calender day

/// </summary>

/// <param name="year">Four-Digit Year</param>

/// <param name="month">Month of year</param>

/// <param name="day">Day of month</param>

/// <returns>The Julian day corresponding to the date</returns>

/// <remarks>Number is returned for start of day.

/// Fractional days should be added later.</remarks>

public static double CalculateJulianDay ( int year , int month , int day )

{

int _year = year , _month = month;

// Is it January or February?

if ( month <= 2 )

{

_year = year - 1;

_month = month + 12;

}

double a = Math.Floor ( _year / 100.0 );

double b = 2 - a + Math.Floor ( a / 4 );

return ( Math.Floor (

365.25 * ( _year + 4716 ) ) +

Math.Floor ( 30.6001 * ( _month + 1 ) ) +

day + b - 1524.5 );

}

/// <summary>

/// Calculate calender date from Julian Day.

/// </summary>

/// <param name="julianDay">Julian Day</param>

/// <returns>String date in form mm/dd/yyyy</returns>

public static string CalculateDateFromJulianDay ( double julianDay )

{

double z = Math.Floor ( julianDay + 0.5 );

double f = ( julianDay + 0.5 ) - z;

double a, alpha;

if ( z < 2299161 )

{

a = z;

}

else

{

alpha = Math.Floor ( ( z - 1867216.25 ) / 36524.25 );

a = z + 1 + alpha - Math.Floor ( alpha / 4 );

}

double b = a + 1524;

double c = Math.Floor ( ( b - 122.1 ) / 365.25 );

double d = Math.Floor ( 365.25 * c );

double e = Math.Floor ( ( b - d ) / 30.6001 );

double day =

b - d - Math.Floor ( 30.6001 * e ) + f;

double month = ( e < 14 ) ? e - 1 : e - 14;

double year =

( month > 2 ) ? c - 4716 : c - 4715;

return

month.ToString ( ) + "/" +

day.ToString ( ) + "/" +

year.ToString ( );

}

/// <summary>

/// Calculate time of Julian Century

/// </summary>

/// <param name="julianDay">Julian Day</param>

/// <returns>A Julian Century corresponding to the Julian Day</returns>

public static double CalculateTimeOfJulianCentury (

double julianDay )

{

return ( julianDay - 2451545.0 ) / 36525.0;

}

/// <summary>

/// Convert centuries since January 2000 to Julian Day.

/// </summary>

/// <param name="time">Number of Julian Centuries since

/// January 2000</param>

/// <returns>the Julian Day corresponding to a Julian Century

/// </returns>

public static double CalculateJulianDayFromTimeOfJulianCentury (

double time )

{

return time * 36525.0 + 2451545.0;

}

/// <summary>

/// calculate the Geometric Mean Longitude of the Sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// Janruary 2000</param>

/// <returns>the Geometric Mean Longitude of the Sun in degrees</returns>

public static double CalculateGeometricMeanLongitudeOfSunInDegrees (

double time )

{

double longitude =

280.46646 + time * ( 36000.76983 + 0.0003032 * time );

while ( longitude > 360.0 ) longitude -= 360.0;

while ( longitude < 360.0 ) longitude += 360.0;

return longitude; // in degrees

}

/// <summary>

/// Calculate the Geometric Mean Anomaly of the Sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>the Geometric Mean Anomaly of the Sun in degrees

/// </returns>

public static double CalculateGeometricMeanAnomalyOfSunInDegrees (

double time )

{

return 357.52911 + time * ( 35999.05029 - 0.0001537 * time );

}

/// <summary>

/// calculate the eccentricity of earth's orbit

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>the unitless eccentricity</returns>

public static double CalculateEccentricityOfEarthOrbit ( double time )

{

return 0.016708634 - time * ( 0.000042037 + 0.0000001267 * time );

}

/// <summary>

/// Calculate the equation of center for the sun.

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>in degrees</returns>

public static double CalculateEquationOfCenterForSun ( double time )

{

double m = CalculateGeometricMeanAnomalyOfSunInDegrees ( time );

double mSine = Math.Sin ( mRadian );

double mSine2 = Math.Sin ( mRadian * 2 );

double mSine3 = Math.Sin ( mRadian * 3 );

return

mSine * ( 1.914602 - time * ( 0.004817 + 0.000014 * time ) ) +

mSine2 * ( 0.019993 - 0.000101 * time ) +

mSine3 * 0.000289;

}

/// <summary>

/// calculate the true longitude of the sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun's true longitude in degrees</returns>

public static double CalculateTrueLongitudeOfSun ( double time )

{

double longitude =

CalculateGeometricMeanAnomalyOfSunInDegrees ( time );

double center =

CalculateEquationOfCenterForSun ( time );

return longitude + center;

}

/// <summary>

/// Calculate the true anamoly of the sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun's true anamoly in degrees</returns>

public static double CalculateTrueAnomalyFromTheSun ( double time )

{

double anomaly =

CalculateGeometricMeanAnomalyOfSunInDegrees ( time );

double center =

CalculateEquationOfCenterForSun ( time );

return anomaly + center;

}

/// <summary>

/// Calculate the distance to the sun in AU

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun radius vector in AUs</returns>

public static double CalculateDistanceToSunInAU ( double time )

{

double vector =

CalculateTrueAnomalyFromTheSun ( time );

double eccentricity =

CalculateEccentricityOfEarthOrbit ( time );

return

( 1.000001018 * ( 1 - eccentricity * eccentricity ) ) /

( 1 + eccentricity * Math.Cos (

ConvertFromDegreesToRadian ( vector ) ) );

}

/// <summary>

/// Calculate the apparent longitude of the sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun's apparent longitude in degrees</returns>

public static double CalculateSunApparentLongitude ( double time )

{

double o = CalculateTrueLongitudeOfSun ( time );

double omega = 125.04 - 1934.136 * time;

// returns lambda

return o - 0.00569 - 0.00478 *

Math.Sin ( ConvertFromDegreesToRadian ( omega ) );

}

/// <summary>

/// Calculate the mean obliquity of the ecliptic

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Mean obliquity in degrees</returns>

public static double CalculateMeanObliquityOfEcliptic ( double time )

{

double seconds =

21.448 - time * (

46.8150 + time * (

0.00059 + time * (

0.001813 ) ) );

return 23.0 + ( 26.0 + ( seconds / 60.0 ) ) / 60.0;

}

/// <summary>

/// Calculate the corrected obliquity of the ecliptic

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Corrected obliquity in degrees</returns>

public static double CalculateCorrectedObliquityOfEcliptic ( double time )

{

double ecliptic = CalculateMeanObliquityOfEcliptic ( time );

double omega = 125.04 - 1934.136 * time;

return ecliptic + 0.00256 *

Math.Cos ( ConvertFromDegreesToRadian ( omega ) );

}

/// <summary>

/// Calculate the right ascension of the sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun's right ascension in degrees</returns>

public static double CalculateRightAscensionOfSun ( double time )

{

double ecliptic = CalculateCorrectedObliquityOfEcliptic ( time );

double lambda = CalculateSunApparentLongitude ( time );

double tanaNum = (

Math.Cos ( ConvertFromDegreesToRadian ( ecliptic ) ) *

Math.Sin ( ConvertFromDegreesToRadian ( lambda ) ) );

Math.Cos ( ConvertFromDegreesToRadian ( lambda ) ) );

}

/// <summary>

/// Calculate the declination of the sun

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Sun's declination in degrees</returns>

public static double CalculateDeclinationOfSun ( double time )

{

double ecliptic = CalculateCorrectedObliquityOfEcliptic ( time );

double lambda = CalculateSunApparentLongitude ( time );

double sineT =

Math.Sin ( ConvertFromDegreesToRadian ( ecliptic ) ) *

Math.Sin ( ConvertFromDegreesToRadian ( lambda ) );

// theta

return ConvertFromRadianToDegrees ( Math.Asin ( sineT ) );

}

/// <summary>

/// Calculate the difference between:

///     true solar time and

///     mean solar time

/// </summary>

/// <param name="time">number of Julian centuries since

/// January 2000</param>

/// <returns>Equation of time in minutes of time</returns>

public static double CalculateDifferenceTimeAndMeanSolarTime ( double time )

{

double epsilon = CalculateCorrectedObliquityOfEcliptic ( time );

double longitude =

CalculateGeometricMeanLongitudeOfSunInDegrees ( time );

double ecliptic = CalculateEccentricityOfEarthOrbit ( time );

double anomaly =

CalculateGeometricMeanAnomalyOfSunInDegrees ( time );

double year =

Math.Tan ( ConvertFromDegreesToRadian ( epsilon ) / 2.0 );

year *= year;

double Sine2Longitude =

Math.Sin ( 2.0 * ConvertFromDegreesToRadian ( longitude ) );

double Sine1Anomality =

Math.Sin ( 1.0 * ConvertFromDegreesToRadian ( anomaly ) );

double Cosine2Longitude =

Math.Cos ( 2.0 * ConvertFromDegreesToRadian ( longitude ) );

double Sine4Longitude =

Math.Sin ( 4.0 * ConvertFromDegreesToRadian ( longitude ) );

double Sine2Anomality =

Math.Sin ( 2.0 * ConvertFromDegreesToRadian ( anomaly ) );

double eclipticTime =

year * Sine2Longitude - 2.0 * ecliptic * Sine1Anomality + 4.0 *

ecliptic * year * Sine1Anomality * Cosine2Longitude - 0.5 *

year * year * Sine4Longitude - 1.25 * ecliptic * ecliptic *

Sine2Anomality;

// in minutes of time

return ConvertFromRadianToDegrees ( eclipticTime ) * 4.0;

}

}

}

There are a lot of functions that confuse me, even though I've done my best to document the functions, but I've never heard of Julian Day, and I don't know where to start off with on how to gather a sunrise and sunset time, other than just having to input a day, month, and year...

Well, my research starts today...

The reason why not to choose a web service (even though my home automation server connects to the Internet) is I plan to develop a home automation software where there are scenarios when a home owner doesn't want a computer to be connected to the Internet but instead, serve as a home automation server for controlling lights.

Monday, July 16, 2007 6:33 AM