使用 Ruby Date 类处理天文数据

发布于 2024-10-19 06:42:02 字数 5059 浏览 8 评论 0原文

〜近似太阳正午

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

作为更新,部分混乱可能是太阳正午是所有的地方 计算从公元前4713年1月1日格林威治中午开始。

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,它一定是一个很小的方差 自公元前 4713 年 1 月 1 日格林威治中午以来的秒数。有关详细信息,请参阅 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 有一种计算儒略日期的方法真是太好了。 我正在研究 NOAA 的 Javascript 代码。

这是我受链接启发而写的一堂课。

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

现在这让我到达那里,但我仍在研究返回这样的数字的方法 作为由最上面的方程计算的那个。尝试一下我们可以看到我们做到了 在 JDN 中获得 0.5 分。谁是对的?红宝石还是 NOAA?


NOAA 使用 2000 年 1 月 1 日的值 2451545.0 从 jd 中减去该值来获取时间 像这样的分数世纪

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

~ Approximate Solar Noon

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

As an update, part of the confusion would be that solar noon is where all
calculations started since January 1, 4713 BC Greenwich noon.

The correct use of Date.ordinal_to_jd has not compensated for this fact. So by
adding or subtracting 12 hours like this:

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

we should get less errors. Just which do we use though since our calculations
start with yesterdays noon?

The code is derived from the two equations from this page Sunrise_equation.

The first answer I got from a user here was that we don't understand the use of
0.0009 and lw / 360. lw / 360 would appear to be a fractional day of arc from the
prime meridian. As for the 0.0009, it must be a small amount of variance in
seconds since January 1, 4713 BC Greenwich noon. see IAU standards for more info

I calculate it to be 0.007776 seconds according to this page.

I have a little bit of info from Date class not including method details.

        =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

As a side note, it's great that Ruby has a way to calculate the julian-date.
I'm looking into the Javascript code from NOAA.

Here is a class that I was inspired to write by the link.

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

Now this gets me there but I'm still researching for the way back for a number such
as the one calculated by the top most equation. Trying this we can see that we do
get a 0.5 in the JDN. Who is right? Ruby or NOAA?


NOAA uses the January 1st 2000 value of 2451545.0 that is subtracted from the jd to get time
in fractional century like this

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

给我一枪 2024-10-26 06:42:02

Ruby 有多种计算儒略日的方法,您需要选择正确的一种。如您所知,NOAA 自公元前 4713 年 1 月 1 日格林威治中午开始计算 JD。它总是以 0.5 结尾,因为他们省略了小数天数。

Ruby 的儒略日很奇怪:

出于科学目的,
方便简单地引用日期
作为一天的计数,从
任意初始日。先说日期
为此选择的是 4713 年 1 月 1 日
公元前。从该日期算起的天数是
儒略日数或儒略日期,
日期中缩写为 jd
班级。这是当地时间,并且
从最初的午夜开始计算
日。

这对于天文用途来说毫无意义。但等等..

更严格的用法是在 UTC 中,并且
从第一天的中午开始计算。
这是在 Date 类中引用的
作为天文儒略日数,
并缩写为 ajd。在日期中
类,天文儒略日
数字包括小数天数。

(rubydoc)

这就是你要找的,ajd。只需获取没有小数天数的内容即可:

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

=> 2455622.5

无需从 NOAA 移植 9 行 JavaScript。 Ruby 为你提供支持! ;)

Ruby has a number of ways of calculating Julian Day and you need to pick the right one. NOAA is calculating the JD since January 1, 4713 BC Greenwich noon as you know. It always ends in .5 because they are leaving out the fractional days.

Ruby's Julian Day is weird:

For scientific purposes, it is
convenient to refer to a date simply
as a day count, counting from an
arbitrary initial day. The date first
chosen for this was January 1, 4713
BCE. A count of days from this date is
the Julian Day Number or Julian Date,
which is abbreviated as jd in the Date
class. This is in local time, and
counts from midnight on the initial
day.

Which makes no sense for astronomical use. but wait..

The stricter usage is in UTC, and
counts from midday on the initial day.
This is referred to in the Date class
as the Astronomical Julian Day Number,
and abbreviated as ajd. In the Date
class, the Astronomical Julian Day
Number includes fractional days.

(rubydoc)

This is what you are looking for, ajd. Just get it without the fractional days:

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

=> 2455622.5

No need to port 9 lines of JavaScript from NOAA. Ruby's got your back! ;)

朮生 2024-10-26 06:42:02

好吧,谢谢大家,我想我现在可以回答我自己的问题了。我忽略了 Date 类中的一个简单方法。它是 Date.day_fraction_to_time(日小数)。由于我现在有一个工作程序,我想与大家分享。

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}"

Well thanks everybody, I guess that I can answer my own question now. I overlooked a simple method in the Date class. It is Date.day_fraction_to_time(day fractional). As I have a working program now I would like to share it with 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}"
孤星 2024-10-26 06:42:02

ordinal_to_jd 方法将 2011 年(公历)索引为 0 的日期转换为儒略历中的相应日期,然后您使用的是 0.0009 的神奇值,我不知道任何原因,然后您添加的比率整个 360* 圆的经度(东经或西经?),然后加上今天的日期(如果您今天评估的话,则为 54)。儒略历和纵比的组合没有多大意义,但是嘿,这是一个很好的数字,因为你混合了 0.0009 英寸。

The method ordinal_to_jd converts the day with index 0 of the year 2011 (Gregorian calendar) to the corresponding day in the Julian calendar, then you are using the magical value of 0.0009 for which i dont know any reason, then you are adding the ratio of your longitude (east or west?) of the whole 360* circle and then adding todays day-of-year (54 if you evaluated it today). The combination of Julian calendar and longitudinal ratio makes not much sense, but hey its a nice number since you mixed a 0.0009 in.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文