Skip to content

Instantly share code, notes, and snippets.

@DouglasAllen
Last active July 11, 2017 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DouglasAllen/2032003 to your computer and use it in GitHub Desktop.
Save DouglasAllen/2032003 to your computer and use it in GitHub Desktop.
A sunrise, transit and equation of time using the wikipedia formula a bit simplified and in Ruby.
```code
# Usage
# Set your time zone offset at the line tz =....
# Mine is -5 hours use 5.5 if you're on a half hour offset.
# The latitude and longitude arguments are my coordinates.
# Yours are most likely different.
# If you are west of Greenwich meridian then use longitude negative.
# If you are south of the equator then use latitude negative.
# Ruby program begins
@jpd_2000 = 2_451_545.0
@latitude = 41.943
@longitude = -88.75
@tz = -6
def local_angle
@longitude / 360.0
end
time = Time.now.utc
@year = Time.now.year
@month = Time.now.month
@day = Time.now.day
include Math
@d2r = PI / 180.0
@r2d = 180.0 / PI
require 'date'
def jpd_date
Date.new(@year, @month, @day).jd
end
# Calculate current Julian Period Cycle
# http://maia.usno.navy.mil/ser7/deltat.data
jps_delta_time = 67.0258 / 86_400.0
$ca = 0.00014 # jps_delta_time or 0.0009 adds too much time
def jpd_cycle
jpd_date - @jpd_2000
end
# Mean Solar Transit for your Local Hour Angle
def jpd_noon
@jpd_2000 + jpd_cycle - local_angle
end
# Solar Mean Anomaly
def mean_anomaly
(357.5291 + 0.98560028 * (jpd_noon - @jpd_2000)) % 360
end
include Math
# Equation of Center
def equation_of_center
ma_r = mean_anomaly * @d2r
1.9148 * sin(ma_r) + 0.0200 * sin(2.0 * ma_r) + 0.0003 * sin(3.0 * ma_r)
end
# ............. lambda_periapsis..............
# An approximation of angle when earth is closest to sun in a new
# year (about the 2nd or 3rd day). There are ways to avoid using it
# but since wikipedia does then I will.
# ............................................
@lambda_periapsis = 180.0 + 102.9372
def ecliptic_longitude
(mean_anomaly + equation_of_center + @lambda_periapsis) % 360
end
def j_eot
0.0053 * sin(mean_anomaly * @d2r) -
0.0069 * sin(2.0 * ecliptic_longitude * @d2r)
end
def j_transit
jpd_noon + j_eot
end
def sine_declination
sin(ecliptic_longitude * @d2r) *
sin(23.436 * @d2r)
end
def declination
asin(sine_declination) * @r2d
end
# Horizon Angle
# Horizon Angle is the angle between Sunrise to Transit or Transit to Sunset.
def cosine_omega
lat_r = @latitude * @d2r
dec_r = declination * @d2r
sin(-0.8333 * @d2r) - sin(lat_r) * sin(dec_r) / cos(lat_r) * cos(dec_r)
end
def hour_angle
acos(cosine_omega) * @r2d
end
def j_set
j_transit + hour_angle / 360.0
end
def j_rise
j_transit - hour_angle / 360.0
end
def jpd_fraction(jpd_time)
fraction = jpd_time - 0.5 - Integer(jpd_time - 0.5)
(fraction * 100_000_000.0).round / 100_000_000.0
end
def _hours(jpd_time)
Integer(jpd_fraction(jpd_time) * 24.0)
end
def _minutes(jpd_time)
hours = _hours(jpd_time)
Integer((jpd_fraction(jpd_time) - hours / 24.0) * 1440.0)
end
def _seconds(jpd_time)
hours = _hours(jpd_time)
minutes = _minutes(jpd_time)
Integer((jpd_fraction(jpd_time) - hours / 24.0 - minutes / 1440.0) * 86_400.0)
end
def julian_period_day_fraction_to_time(jpd_time)
hours = _hours(jpd_time)
minutes = _minutes(jpd_time)
seconds = _seconds(jpd_time)
Time.new(@year,
@month,
@day,
hours,
minutes,
seconds) +
@tz * 3600
end
# Output results
text = <<-HEREDOC
The current time UTC = #{time}
Current Julian Cycle = #{jpd_cycle}
Julian Mean Solar transit = #{jpd_noon}
Approximate Julian EOT = #{j_eot}
Julian True Solar transit = #{j_transit}
Julian Sunrise #{j_rise}
Julian Sunset #{j_set}
Local Mean Noon #{julian_period_day_fraction_to_time(jpd_noon)}
Local Noon #{julian_period_day_fraction_to_time(j_transit)}
Local Sunrise #{julian_period_day_fraction_to_time(j_rise)}
Local Sunset #{julian_period_day_fraction_to_time(j_set)}
HEREDOC
puts text
```
@DouglasAllen
Copy link
Author

@huttarl
Copy link

huttarl commented Sep 23, 2015

I'm trying to understand Wikipedia's Sunrise equation page to help my daughters in a math experiment; specifically https://en.wikipedia.org/wiki/Sunrise_equation#Calculate_current_Julian_cycle The meaning of Julian date is clear, but what is the conceptual definition of current Julian cycle? We take our current Julian date (JD), subtract the JD of Jan 1, 2000, subtract our longitude as a fraction of 360 degrees, and round to the nearest integer ... but what does this mean? What is the Julian cycle? (We then use this to compute solar noon.) Thanks for any help you can offer in how to conceptualize this!

@DouglasAllen
Copy link
Author

DouglasAllen commented Nov 4, 2016

I use the term Julian Cycle loosely for the number of days since the year 2000/01/01 12:00. 

This is a constant in most calculations of this sort. Even for planets and stars.

It's the reference point that the formula are based on. 

We have to add on our longitude as time for convenience paying attention to the direction in terms of Earth rotation. 

A western longitude means the point in space comes later than our earthly zero reference point which was the Greenwich Mean Time(GMT).

https://equationoftime.herokuapp.com/gm 

But it has since been changed to Coordinated Universal Time(UTC) probably to avoid confusion with sidereal terms like GMST and GAST.

East is ahead of that point by the number of degrees divided by 15.0 to yield it in hours. 

We  may eliminate that step and just go for the Julian offset longitude / 360.0. Julian is a daily number. 1 day / 24.0 hours gives time.

(see http://curious.astro.cornell.edu/physics/125-observational-astronomy/timekeeping/calendars/763-how-was-the-starting-point-for-the-julian-date-system-chosen-advanced)...

 or some equivalent site. 

Joseph named this system after his father. He could have called it Joseph Numbers but we honor a mans will sometimes.

Just keep in mind that I just roughed this bit of code together rather quickly just to see it working.

It may some errors but I've done a lot of testing on the EOT gem that I posted the link to. 

It's all Ruby code except for some Ruby C extensions. 

A nice wrapper for the IAU Standards Of Fundamental Astronomy (SOFA) C library is a gem is called Celes. 

https://rubygems.org/gems/celes/versions/0.0.1

@DouglasAllen
Copy link
Author

This was a long time ago and it's not best practice for Ruby but was a quick scratch together to see if it works kind of thing. I look at it now and see how horrible it is. Rubocop would beat me to my grave. It isn't even OOP because there's no class or instance variables. I'm working on one now though and will post it soon. Thanks for your interest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment