木星の中央経度計算 API

はじめに

府中天文同好会(FAS)のサイトで公開されている、 佐藤幹哉さんが作成された CGI のソースコードをいただいたので、若干の修正を入れたうえで Web APIに仕立ててみました。(計算部分はほぼ佐藤さんの書かれたコードのまま)
公開することをご快諾いただけたので as isで公開させていただきます。

使用例(1) --- Ajaxを使って

計算ボタンをクリックすると結果が(画面遷移なしで)こちらに表示されます
CM-I CM-II CM-III MJD status
jQueryの ajax()を使っている部分の抜粋
function callapi() {
    var t = $('#time_input').val() + $('input[name=tz]:checked').val();
    $.ajax({
        url: 'https://www.carina.gr.jp/~yamane/Jupiter_CM/api/calc_jupiter_cm',
        type: 'post',
        cache: false,
        data: { 'time' : t },
        dataType: 'json'
    })
    .done(function(json, status, xhr) {
        $('#cm1').html(json.cm1);
        $('#cm2').html(json.cm2);
        $('#cm3').html(json.cm3);
        $('#mjd').html(json.mjd);
        $('#status').html(json.status);
    })
    .fail(function(xhr, status, error) {
        alert('Error: ' + error);
    });
}
          

詳細はこのページのソースを見ていただければ...

使用例(2) --- コマンドラインから

      $ curl -F 'time=2019-09-16T09:12:34+0000' https://www.carina.gr.jp/~yamane/Jupiter_CM/api/calc_jupiter_cm
      {"status":0,"cm1":"264.7","cm3":"37.5","mjd":43722.8837268519,"cm2":"41.2","apiversion":"v0.9"}
    
URL
https://www.carina.gr.jp/~yamane/Jupiter_CM/api/calc_jupiter_cm
method
POST
Parameter
time (ISO 8601形式の日付文字列および ISO 8601の分:秒を分の小数とした形式)

      例1: 2019-09-15T22:34:56+0900
      例2: 2019-09-15T22:34.9+0900

Return
以下の値が JSONで返される。(順不同)
  • cm1: CM-I
  • cm2: CM-II
  • cm3: CM-III
  • mjd: 入力された timeを MJD(修正ユリウス日)に変換した値
  • status: 0:正常終了 / -1:入力の不備 / -2:その他のエラー
#! /usr/bin/perl
#
#   calc_jupiter_cm
#
#   Created: 2019/09/14  Satoru Yamane  Initial revision.
#                                       Special thanks to Mikiya Sato.
#

use strict;

use JSON qw/ encode_json /;
use Log::Log4perl;

use CGI qw/:cgi-lib/;

# ---------------------------
# Globals
# ---------------------------
my $version = "jupcmcal.cg-v1.1";
my $APIver = "v0.9";
our %form;
my %ret = (
	'status' => -99,	# undefined error
	'mjd' => -1, 'cm1' => -1, 'cm2' => -1, 'cm3' => -1,
	'apiversion' => $APIver,
);

# ---------------------------
# main
# ---------------------------
Log::Log4perl::init('./log4perl.conf');
my $logger = Log::Log4perl::get_logger("mylogger");

my $srcIP = $ENV{'REMOTE_ADDR'};
$logger->info("$0 started (IP=$srcIP).");

ReadParse(*form);
my $t = $form{'time'};	# ISO 8061 format is expected
$logger->debug("t=$t");

print("Content-type: application/json\n\n");

# --------------------------
# parse time string (ISO 8061)
# --------------------------
my ($yy, $mm, $dd, $hh, $mi, $ss, $tz) = ();

if ($t =~ /(\d{4})-*(\d{2})-*(\d{2})T(\d{2})\:*(\d{2})\:*(\d{2})(Z|[+-]\d{4})/) {
	($yy, $mm, $dd, $hh, $mi, $ss, $tz) = ($1, $2, $3, $4, $5, $6, $7);
} elsif ($t =~ /(\d{4})-*(\d{2})-*(\d{2})T(\d{2})\:*(\d{2})\.(\d{1})(Z|[+-]\d{4})/) {
	($yy, $mm, $dd, $hh, $mi, $ss, $tz) = ($1, $2, $3, $4, $5, $6, $7);
	$ss *= 6;
} else {
	$logger->error("'$t': Invalid time format.");
	$ret{'status'} = -1;
	clean_exit(1);
}
$logger->debug("yy=$yy, mm=$mm, dd=$dd, hh=$hh, mi=$mi, ss=$ss, tz=$tz");

# --------------------------
# final validation
# --------------------------
if ($yy < 1901
 || $mm < 1 || $mm > 12
 || $dd < 1 || $dd > 31
 || $hh < 0 || $hh > 30
 || $mi < 0 || $mi > 60
 || $ss < 0 || $ss > 60) {
	$ret{'status'} = -1;
	clean_exit(9);
}
$logger->debug("validation passed. continue...");

# --------------------------
# calc MJD and CM
# --------------------------
my $mjd = MJD($yy, $mm, $dd, $hh, ($mi + $ss / 60), $tz);
$ret{'mjd'} = $mjd;

my ($cm1, $cm2, $cm3) = CM($mjd);
$ret{'cm1'} = sprintf("%3.1f", $cm1);
$ret{'cm2'} = sprintf("%3.1f", $cm2);
$ret{'cm3'} = sprintf("%3.1f", $cm3);
$ret{'status'} = 0;

clean_exit(0);

# -------------------------------------
# clean_exit ---
# -------------------------------------
sub clean_exit {
	my $rc = shift;

	$logger->info("$0 finished. (rc=$rc)");
	print encode_json(\%ret);

	exit ($rc);
}

# -------------------------------------
# CM --- calc CM
# -------------------------------------
sub CM {
	my ($mjd) = shift;
	my ($cm1, $cm2, $cm3) = ();	# return values

	my $RAD = 0.0174532925199433;

	my $IR = (134.630 + $mjd * 0.00111587) * $RAD;
	my $JR = (358.476 + $mjd * 0.9856) * $RAD;
	my $KR = (225.328 + $mjd * 0.083085 + 0.33 * sin($IR)) * $RAD;

	my $L = 221.650 + $mjd * 0.902518 - 0.33 * sin($IR);
	my $M = 1.916 * sin($JR) + 0.02  * sin(2 * $JR);
	my $N = 5.552 * sin($KR) + 0.167 * sin(2 * $KR);

	my $OR = ($L + $M - $N) * $RAD;

	my $P = 1    - 0.0167 * cos($JR) - 0.00014 * cos(2 * $JR);
	my $Q = 5.21 - 0.252  * cos($KR) - 0.0061  * cos(2 * $KR);

	my $R = sqrt($Q * $Q + $P * $P - 2 * $Q * $P * cos($OR));

	my $SSI = $P * sin($OR) / $R;
	my $SCO = sqrt(1 - $SSI * $SSI);
	my $SR = atan2($SSI , $SCO);
	my $S = $SR / $RAD;

	my $sk = ($S < 0) ? 1 : -1;

	my $T = 877.8169088 * ($mjd - $R / 173) + $S - $N + 269.10 + 57.3 * $sk * (sin($SR * 0.5)) ** 2;
	my $U = 870.1869088 * ($mjd - $R / 173) + $S - $N + 291.04 + 57.3 * $sk * (sin($SR * 0.5)) ** 2;
	my $V = 870.4529088 * ($mjd - $R / 173) + $S - $N + 177.04 + 57.3 * $sk * (sin($SR * 0.5)) ** 2;

	$cm1 = $T - 360 * int($T / 360.0);
	$cm2 = $U - 360 * int($U / 360.0);
	$cm3 = $V - 360 * int($V / 360.0);

	$logger->debug("CM($mjd) ==> $cm1, $cm2, $cm3");
	($cm1, $cm2, $cm3) ;
}

# -------------------------------------
#  MJD --- Calc MJD
# -------------------------------------
sub MJD {
	my ($sy, $sm, $sd, $sh, $smin, $stz) = @_;
	my ($mjd);

	$logger->debug("enter MJD($sy, $sm, $sd, $sh, $smin, $stz)");
	if ($sm > 2) {
		$sy = $sy - 1900;
		$sm = $sm;
	} else {
		$sy = $sy - 1901;
		$sm = $sm + 12;
	}
	my $dt = 0;
	if ($stz =~ /([+-]*\d{2})(\d{2})/) {
		my ($h, $m) = ($1, $2);
		$dt = ($h / 24.0) + ($m / 24.0 / 60);
		$logger->debug("MJD() h=$h / m=$m ==> dt=$dt");
	}
	$mjd = int($sy * 365.25) + int(30.6 * $sm + 0.6) + $sd - 34 + ($sh / 24.0) + ($smin / 1440) + 0.5 - $dt;
	$logger->debug("exit MJD() ==> $mjd");

	($mjd) ;
}

__END__
      
Copyright © 2019 Satoru Yamane