Использование класса Ruby Date для астрономических данных

Приблизительный солнечный полдень

lw = 88.743  # my longitude

jdate = Date.ordinal_to_jd(Time.now.year, Time.now.yday)
n = (jdate - 2451545 - 0.0009 - lw / 360).round  # lw is users longitude west of 0.
j_noon = 2451545 + 0.0009 + lw / 360 + n 
puts j_noon

=> 2455616.24740833

В качестве обновления, часть путаницы будет заключаться в том, что в солнечный полдень все расчеты начались с 1 января 4713 года до н.э. по Гринвичу.

Правильное использование Date.ordinal_to_jd не компенсировало этот факт. Таким образом, добавляя или вычитая 12 часов, как это:

jdn = Date.ordinal_to_jd(Time.now.year, Time.now.yday) - 0.5

мы должны получить меньше ошибок. Что же мы используем, так как наши расчеты начинаются с вчерашнего дня?

Код получен из двух уравнений с этой страницы Sunrise_equation.

Первый ответ, который я получил от пользователя, заключался в том, что мы не понимаем, как использовать 0,0009 и lw / 360. lw / 360 может показаться дробным днем ​​дуги от основного меридиана. Что касается 0,0009, это должно быть небольшое количество отклонений в секундах с 1 января 4713 г. до н.э. по Гринвичу. см. стандарты IAU для получения дополнительной информации

Я рассчитываю, что это будет 0,007776 секунд в соответствии с этой страницей.

У меня есть немного информации из класса Date, не включая детали метода.

        =begin
--------------------------------------------------------------------- Class: Date
Class representing a date.

See the documentation to the file date.rb for an overview.

Internally, the date is represented as an Astronomical Julian Day Number, ajd. 
The Day of Calendar Reform, sg, is also stored, for conversions to other date formats. 
(There is also an of field for a time zone offset, 
but this is only for the use of the DateTime subclass.)

A new Date object is created using one of the object creation class methods named  
after the corresponding date format, and the arguments appropriate to that date
format; for instance, Date::civil() 
(aliased to Date::new()) with year, month, and day-of-month, or Date::ordinal() with
year and day-of-year.

All of these object creation class methods also take the Day of Calendar Reform as an
optional argument.

Date objects are immutable once created.

Once a Date has been created, date values can be retrieved for the different date
formats supported using instance methods. For instance, #mon() gives the Civil month,
#cwday() gives the Commercial day of the week, and #yday() gives the Ordinal day of
the year. Date values can be retrieved in any format, regardless of what format was
used to create the Date instance.

The Date class includes the Comparable module, allowing date objects to be compared
and sorted, ranges of dates to be created, and so forth.

---------------------------------------------------------------------------------

Includes:
Comparable(<, <=, ==, >, >=, between?)

Constants:
MONTHNAMES:      [nil] + %w(January February March April May June July August
                            September October November December)
DAYNAMES:        %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
ABBR_MONTHNAMES: [nil] + %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
ABBR_DAYNAMES:   %w(Sun Mon Tue Wed Thu Fri Sat)
ITALY:           2299161
ENGLAND:         2361222
JULIAN:          Infinity.new
GREGORIAN:       -Infinity.new

Class methods:
_load, _parse, _strptime, ajd_to_amjd, ajd_to_jd, amjd_to_ajd, civil, civil_to_jd,
commercial, commercial_to_jd, day_fraction_to_time, gregorian?, gregorian_leap?, jd,
jd_to_ajd, jd_to_civil, jd_to_commercial, jd_to_ld, jd_to_mjd, jd_to_ordinal,
jd_to_wday, julian?, julian_leap?, ld_to_jd, mjd_to_jd, new, now, ordinal,
ordinal_to_jd, parse, s3e, strptime, time_to_day_fraction, today, valid_civil?,
valid_commercial?, valid_jd?, valid_ordinal?, valid_time?

Instance methods:
+, -, <<, <=>, ===, >>, _dump, ajd, amjd, asctime, civil, commercial, ctime, cwday,
cweek, cwyear, day, day_fraction, downto, england, eql?, gregorian, gregorian?, hash,
hour, inspect, italy, jd, julian, julian?, ld, leap?, mday, min, mjd, mon, month,
new_offset, new_start, next, next_day, offset, ordinal, sec, sec_fraction, start,
step, strftime, succ, time, to_s, to_yaml, upto, wday, weeknum0, weeknum1, wnum0, 
wnum1, yday, year, zone

=end

Примечательно, что у Ruby есть способ вычислить юлианскую дату. Я смотрю на код Javascript от NOAA.

Вот класс, который меня вдохновил написать по ссылке.

class JulianDayNumber

  def initialize(year = 2000, month = 1, day = 1) #defaults to Jan. 01, 2000
    @year = year
    @month = month
    @day = day
  end

  def calcJDN

    if (@month <= 2) then 
      @year -= 1
      @month += 12
    end

    varA = (@year/100).floor
    varB = 2 - varA + (varA/4).floor

    jdn = (365.25*(@year + 4716)).floor \
           + (30.6001*(@month+1)).floor \
           + @day + varB - 1524.5

    return jdn
  end

end

jd = JulianDayNumber.new(2011, 3, 2)
julianday = jd.calcJDN
puts julianday

=> 2455622.5

Теперь это меня заводит, но я все еще исследую путь назад для числа, такого как вычисленное по самому верхнему уравнению. Пытаясь это, мы видим, что мы получаем 0,5 в JDN. Кто прав? Рубин или НОАА?


NOAA использует значение 1 января 2000 года 2451545.0, которое вычитается из jd, чтобы получить время в дробном веке, как это

    def calcTimeJulianCent(j)
      t = (j - 2451545.0)/36525.0
      return t
    end 

3 ответа

У Руби есть несколько способов подсчета Юлианского Дня, и вам нужно выбрать правильный. NOAA рассчитывает JD с 1 января 4713 г. до н.э. Гринвичский полдень, как вы знаете. Это всегда заканчивается.5, потому что они опускают дробные дни.

Юлианский День Руби странный:

В научных целях удобно называть дату просто подсчетом дней, считая от произвольного начального дня. Дата, впервые выбранная для этого, была 1 января 4713 г. до н.э. Отсчет дней с этой даты - это юлианский номер дня или юлианская дата, которая сокращенно обозначается как jd в классе Date. Это по местному времени и считается с полуночи первого дня.

Что не имеет смысла для астрономического использования. но ждать..

Более строгое использование указывается в UTC и считается с полудня первого дня. В классе Date это называется астрономическим юлианским номером дня и сокращенно ajd. В классе Date астрономический юлианский номер дня включает дробные дни.

( рубидок)

Это то, что вы ищете, ажд. Просто получите это без дробных дней:

julianday = Date.civil(@year, @month, @day).ajd
puts julianday

=> 2455622.5

Нет необходимости переносить 9 строк JavaScript из NOAA. Руби получила твою спину!;)

Ну, спасибо всем, я думаю, что теперь я могу ответить на свой вопрос. Я пропустил простой метод в классе Date. Это Date.day_fraction_to_time(дробный день). Поскольку у меня есть рабочая программа, я хотел бы поделиться ею с eveyone.

include Math
to_r = PI / 180.0
to_d = 180.0 / PI

latitude = 41.9478 # my latitude
longitude = 88.74277  # my longitude
lw = longitude / 360

jdate = Date.civil(Time.now.year, Time.now.month, Time.now.day).ajd
jdate = (jdate * 2).to_i/2 + 1

n = (jdate - 2451545 - 0.0009 - lw).round
j_noon = 2451545  + 0.0009   + lw  + n
mean_anomaly = (357.52911 + 0.98560028 * (jdate - 2451545)) % 360
center = 1.9148 * sin(mean_anomaly * to_r) + 0.0200 * sin(2 * mean_anomaly * to_r) + \
         0.0003 * sin(3 *  mean_anomaly * to_r)
lambda = (mean_anomaly + 102.9372 + center + 180) % 360
j_transit = j_noon + (0.0053 * sin(mean_anomaly * to_r)) - (0.0069 * sin(2 * lambda * \
            to_r))
delta = asin(0.397753054 * sin(lambda * to_r)) * to_d
omega = acos(sin(-0.83 * to_r)/cos(latitude * to_r) * cos(delta * to_r) \
        - tan(latitude * to_r) * tan(delta * to_r)) * to_d
j_set = 2451545 + 0.0009 + ((omega + longitude)/360 + n + 0.0053 * sin(mean_anomaly * \
        to_r)) - 0.0069 * sin(2 * lambda * to_r)

j_rise = j_transit - (j_set - j_transit)

rise = Date.day_fraction_to_time(j_rise - jdate)# + 0.25 for + 6 hours
risehour = rise[0].to_s
risemin = rise[1].to_s
risetime = "#{risehour}:#{risemin}"
puts "Sun rise = #{risetime} UTC"

transit = Date.day_fraction_to_time(j_transit - jdate)# + 0.25
transithour = transit[0].to_s
transitmin = transit[1].to_s
transittime = "#{transithour}:#{transitmin}"
puts "Solar noon = #{transittime} UTC"

set = Date.day_fraction_to_time(j_set - jdate)# + 0.25
sethour = set[0].to_s
setmin = set[1].to_s
settime = "#{sethour}:#{setmin} UTC"
puts "Sun set = #{settime}"

Метод ordinal_to_jd преобразует день с индексом 0 года 2011 (григорианский календарь) в соответствующий день в юлианском календаре, затем вы используете магическое значение 0,0009, для которого я не знаю никакой причины, затем вы добавляете соотношение Ваша долгота (восток или запад?) всего круга 360*, а затем добавление сегодняшнего дня года (54, если вы оценили его сегодня). Сочетание юлианского календаря и продольного отношения не имеет особого смысла, но эй, это хорошее число, поскольку вы смешали 0,0009 дюйма.

Другие вопросы по тегам