mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

Ruby - 地球自転速度補正値 ΔT の取得(USNO から)!

[ プログラミング, 暦・カレンダー ] [ Ruby ]

こんばんは。

以前、地球自転速度補正値 ΔT の計算を Ruby で実装しました。

今回は、計算して取得するのではなく、 USNO(The United States Naval Observatory; アメリカ海軍天文台)による確定値と推定値を取得する処理を Ruby で実装してみました。

0. 前提条件

  • Ruby 2.5.1-p57 での動作を想定。
  • ΔT 一覧を取得するページは「こちら」。

1. Ruby スクリプトの作成

  • Shebang ストリング(1行目)では、フルパスでコマンド指定している。(当方の慣習
  • User Agent UA の PG(Bot) 名やメールアドレスは自分のもので置き換えること。
get_delta_t_usno.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#! /usr/local/bin/ruby
# coding: utf-8
#---------------------------------------------------------------------------------
#= USNO(アメリカ海軍天文台) から delta T(ΔT) を取得
#  : 確定データは
#    [Delta T determinations](http://maia.usno.navy.mil/ser7/deltat.data)
#    から、推定データは
#    [Delta T predictions](http://maia.usno.navy.mil/ser7/deltat.preds)
#    から取得する。
#
# date          name            version
# 2018.06.20    mk-mode.com     1.00 新規作成
#
# Copyright(C) 2018 mk-mode.com All Rights Reserved.
#---------------------------------------------------------------------------------
# 引数 : UTC (YYYYMMDD 形式)
#        * 無指定ならシステム日時を UTC とみなす
#---------------------------------------------------------------------------------
#++
require "open-uri"

class GetDeltaTUsno
  USAGE = "[USAGE] ./get_delta_t_usno.rb [YYYYMMDD]"
  URL_D = "http://maia.usno.navy.mil/ser7/deltat.data"
  URL_P = "http://maia.usno.navy.mil/ser7/deltat.preds"
  UA    = "<BOT_NAME> (by Ruby/#{RUBY_VERSION}, Administrator: <MAIL_ADDRESS>)"

  def initialize
    ymd = ARGV.shift
    ymd ||= Time.now.strftime("%Y%m%d")
    if ymd !~ /^\d{8}$/
      puts USAGE
      exit 0
    end
    @date = "#{ymd[0, 4]}-#{ymd[4, 2]}-#{ymd[6, 2]}"
    @delta_t = 0  # delta T 初期値
    @dp = ""      # 確定/推定値区分(推定値なら "*")
  end

  def exec
    get_determination  # 確定データ取得
    get_prediction     # 推定データ取得
    get_delta_t        # delta_T 取得
    display            # 結果出力
  rescue => e
    $stderr.puts "[#{e.class}] #{e.message}"
    e.backtrace.each { |tr| $stderr.puts "\t#{tr}"}
    exit 1
  end

  private

  # ------------------------------------
  # 確定データ取得
  # ------------------------------------
  def get_determination
    html = open(URL_D, "r:utf-8", {"User-Agent" => UA}) { |f| f.read }
    @data = html.split(/[\r\n]+/).map do |line|
      items = line.sub(/^\s+/, "").split(/\s+/)
      date = "%04d-%02d-%02d" % [*items[0, 3]]
      @date_max = date
      [date, items[-1].to_f, "D"]
    end
  rescue => e
    raise
  end

  # ------------------------------------
  # 推定データ取得
  # ------------------------------------
  def get_prediction
    html = open(URL_P, "r:utf-8", {"User-Agent" => UA}) { |f| f.read }
    html.split(/[\r\n]+/).each do |line|
      items = line.sub(/^\s+/, "").split(/\s+/)
      next if /[\d\.]+/ !~items[0]
      year, year_frac = items[0].split(/\./)
      year = year.to_i
      case year_frac
      when "00"; month = 1
      when "25"; month = 4
      when "50"; month = 7
      when "75"; month = 10
      end
      date = "%04d-%02d-01" % [year, month]
      next if date <= @date_max
      @data << [date, items[1].to_f, "P"]
    end
  rescue => e
    raise
  end

  # ------------------------------------
  # delta T 取得
  # ------------------------------------
  def get_delta_t
    @data.reverse.each_with_index do |d, i|
      if d[0] <= @date
        break if i == 0
        @delta_t = d[1]
        @dp = "*" if d[2] == "P"
        break
      end
    end
  rescue => e
    raise
  end

  # ------------------------------------
  # 結果出力
  # ------------------------------------
  def display
    puts "[#{@date}] delta_T = #{@delta_t} selc. #{@dp}"
  rescue => e
    raise
  end
end

GetDeltaTUsno.new.exec if __FILE__ == $0

2. Ruby スクリプトの実行

まず、実行権限を付与。

1
$ chmod +x get_delta_t_usno.rb

そして、コマンドライン引数に UTC(協定世界時)を YYYYMMDD の書式で指定して実行する。(引数無指定なら、システム日付を UTC とみなす)

1
2
$ ./get_delta_t_usno.rb 20180620
[2018-06-20] delta_T = 69.14 sec. *
  • 推定値の場合は行末に * が付与される。

人工衛星の正確な軌道計算等に利用できるでしょう。

ちなみに、今回の方法を応用して、 IERS(国際地球回転観測事業; International Earth Rotation and Reference systems Service)提供の Polar Motion(地球の極運動)のデータも取得できます。

以上。

Comments