Использование класса Ruby Date для астрономических данных - PullRequest
2 голосов
/ 23 февраля 2011

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

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.Кто прав?Ruby или NOAA?


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

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

Ответы [ 3 ]

3 голосов
/ 08 марта 2011

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

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

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

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

Более строгое использование в UTC, и отсчитывает с полудня первого дня. Это упоминается в классе Дата как астрономический юлианский номер дня, и сокращенно как AJD. В дату класс, астрономический юлианский день Число включает дробные дни.

( rubydoc )

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

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

=> 2455622.5

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

0 голосов
/ 12 марта 2011

Ну, спасибо всем, я думаю, что теперь я могу ответить на свой вопрос.Я пропустил простой метод в классе 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}"
0 голосов
/ 23 февраля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...