Link to home
Start Free TrialLog in
Avatar of Joe Howard
Joe HowardFlag for United States of America

asked on

How do sunrise and sunset times change with altitude

Assuming a given time for sunrise or sunset at sea level, what adjustment have to be made to those times for a given altitude (i.e. 2400 feet).
Avatar of d-glitch
d-glitch
Flag of United States of America image

At sunrise, you see the sun's disks peeking over the horizon.
If you are higher, you can see farther (at least in theory).
What are doing and what sort of accuracy do you think you need?
Do you actually have an horizon?  If so, what is its altitude?
Ask an Astronomer is run by volunteers in the Astronomy Department at Cornell University.

How do sunrise and sunset times change with altitude?
At most latitudes on the Earth, the effect of increased altitude is the same: it makes the Sun rise earlier and set later than it would at that same location from the ground. To make things simple, let's assume that you are in a plane over the ocean, at the equator at sunset. In that case, straightforward trigonometry indicates that at a typical commercial airplane altitude of 12000 metres, you can see an extra 2 degrees "around" the Earth. Since the Earth moves around the Sun at a rate of a quarter of a degree a minute, it means that at this altitude, sunset occurs 8 minutes later than it would from the ground. The variation with altitude is approximately linear, and so we conclude that sunset is later by 1 minute for every 1.5 kilometres in altitude, and that sunrise is earlier by the same amount.
http://curious.astro.cornell.edu/about-us/161-our-solar-system/the-earth/day-night-cycle/189-how-do-sunrise-and-sunset-times-change-with-altitude-intermediate
Avatar of Joe Howard

ASKER

@d-glitch
The sunrise and sunset times I have are calculated using the NOAA algorithms, unfortunately, the algorithm doesn't account for the elevation factor. I'm looking for an algorithm to correct those times.

@Paul Sauvé
Perhaps I shall ask this question on that website... Simple observation proves that answer wrong. A difference in elevation of several hundred feet can cause differences larger than 1 minute. Also I think this may change throughout the year, since the sun's zenith should probably be part of the equation.
SOLUTION
Avatar of Paul Sauvé
Paul Sauvé
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@ Paul
Thanks for the links.
I found an algorithm to correct the zenith based on the observers elevation. https://github.com/Yitzchok/Zmanim/blob/master/src/Zmanim/Calculator/AstronomicalCalculator.cs
Although I'm not sure what to do with it as I'm looking to correct the NOAA times, not to calculate the times using a different algorithm.
Hi
Algorithm to correct the zenith is to correct sun height at sunrise/set time. It's not zero but negative taking into account sun radius (approx 16', actually 15.8'-16.2'), refraction (approx 34') and dip of the horizon due to observer altitude (d_in_minutes=1.76*sqrt(e_in_meters)). Then, to calculate sunrise/set time you need use spherical trigonomethry formula depended on sun declination, right ascending and corrected height (see above), and observer position - latitude and longitude. So time correction for sunrise/set is not linear, and you can get only approximate time correction. As @Paul Sauvé already wrote it's 1 minute per 1.5 km at equator. To get time difference at any other latitude (in minutes) use
(1/cos (latitude)) * height_in_meters/1500, or
(1/cos (latitude)) * height_in_feet/4921.26
Here is a code:
    Private Function Radians(degrees As Double)
        Return Math.PI * degrees / 180
    End Function
    'lat - latitude in degrees, h - altitude in meters
    'return time correction in seconds
    Private Function TimeCorrection_Meters(lat As Double, h As Double) As Double
        Return (1 / Math.Cos(Radians(lat))) * h / 1500 * 60
    End Function
    'lat - latitude in degrees, h - altitude in feet
    'return time correction in seconds
    Private Function TimeCorrection_Feet(lat As Double, h As Double) As Double
        Return (1 / Math.Cos(Radians(lat))) * h / 4921.26 * 60
    End Function

Open in new window

So, for altitude 2400 feet at latitude 30 deg 35 min will be
Debug.Print(TimeCorrection_Feet(30 + 35 / 60, 2400)) = 34 sec
Note that this value is aprroximate since it does not take into account the tilt of the earth's axis (sun declination - i.e. position on ecliptic). The error is minimum for equinox (march and september) and maximum (up to 1/2 minute or more at latitude >=65 degrees) for solstice (June and december)
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks guys, I'm not positive that this is the most accurate formula (as different online calculators give different results) but for now it is good enough.

@Ark I really appreciate the time you've given this question and the clear explanation too.
@Paul I appreciate your willingness to help and the links you posted.
To get accurate results you need your own calculator, based on correct formulaes, including eye altitude. Here is my dll for astronomical calculation (vb written, .NET 4.0)
Astro.zip
It contains a number of astronomical functions as well as SkyMap user control you can use in WinForms. Here is a simple console application utilizing Astro.dll:
Imports Astro

Module Module1

    Sub Main()
        Planets.Init()
        AstroSettings.Temperature = -10 'Celsius degrees
        AstroSettings.Pressure = 1020 'hPa
        AstroSettings.Height = 2400 * 0.3048 'meters
        AstroSettings.Culture = Globalization.CultureInfo.InvariantCulture 'Russian is by defaul
        Dim pos As New Position(43.1, 131.9) 'Vladivostok,Russia
        AstroSettings.TimeZone = TimeZoneInfo.Local 'or set timezone you need
        '==========or================
        Dim t As Town
        Towns.Init()
        t = Towns.Find("New York")
        If Not t Is Nothing Then
            pos = New Position(t.Latitude, t.Longitude)
            AstroSettings.TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
        End If
        '=============================
        Planets.Refresh(DateTime.UtcNow, pos) 'or set UTC date and time you need
        Console.WriteLine("Rise/Set{1} on {0}", _
                          AstroSettings.LocalDateTime.ToString("D", AstroSettings.Culture), _
                          If(t Is Nothing, "", " at " & t.Name))
        Console.WriteLine("Position: {0} {1}", _
                          Astro.Format.Latitude(AstroSettings.Position.Latitude), _
                          Astro.Format.Longitude(AstroSettings.Position.Longitude))
        Console.WriteLine("At elevation: {0:#0.0 meters} ({1:#0.0 feet})", _
                          AstroSettings.Height, AstroSettings.Height / 0.3048)
        Dim lineSeparator As String = New String("="c, 53)
        Console.WriteLine(lineSeparator)
        Console.WriteLine("{0,-12}{1,-12}{2,-12}{3}", "Body", "Rise", "Set", "UpperTransit")
        Console.WriteLine(lineSeparator)
        Dim offset = AstroSettings.TZ_Offset
        For Each p In Planets.Sorted
            Console.Write("{0, -11}", p.EnglishName)
            Console.Write("{0,-10:HH:mm:ss}", UraniaTime.UTCToLocal(p.Rise.Time, offset))
            Console.Write("{0,-10:HH:mm:ss}", UraniaTime.UTCToLocal(p.Set.Time, offset))
            Console.Write("{0,10:HH:mm:ss} ({1})", _
                          UraniaTime.UTCToLocal(p.UpperTransit.Time, offset), _
                          Astro.Format.Degrees(p.UpperTransit.Height))
            Console.WriteLine()
        Next
        Console.WriteLine(lineSeparator)
        Console.WriteLine("Sun (Now, {0:HH:mm:ss dd MMMM yyyy}):", AstroSettings.LocalDateTime)
        Console.WriteLine("Height {0}, Azimuth {1}", _
                          Format.Degrees(Planets.Sun.Horizon.Altitude), _
                          Format.Degrees(Planets.Sun.Horizon.Azimuth))
        Constellations.Init()
        Console.WriteLine("In constelation {0}, In zodiac {1}", Planets.Sun.InConstellation, Planets.Sun.InZodiac)
        Console.WriteLine("Distance to Earth: {0:#,0} kilometers", Planets.Earth.Distance * Constants.AU)
        Console.ReadKey()
    End Sub

End Module

Open in new window

Thanks.
Just noting that the dll file in the attached zip file has the txt extension instead of dll.
EE doesn't allow uploading files with *.dll extensions. Just rename txt with dll
Here is GUI application.
NightSky.zip
1. Change extensions for all files in resource folders("ru","ru-RU","en-US") from *.txt to *.dll
2. Change extension for NightSky.txt to NightSky.exe
3. Add Astro.dll to then same folder where NightSky.exe situiated
4. Run executable
PS. To allow intellisence description for dll methods/properties, add this xml file
Astro.xml