Java で MJD
〜 修正ユリウス日を計算 〜
2023-10-10 作成 福島
TOP > asob > java-mjd
[ TIPS | TOYS | OTAKU | LINK | MOVIE | CGI | AvTitle | ConfuTerm | HIST | AnSt | Asob ]

本稿は Python 版と同様の理由で記述しています。

日付の加減算を装備していない他言語への実装や、学習のために本稿を参考にしてください。

Java で MJD の加減算をするには以下のように簡単に記述できます。
LocalDate は紀元前も扱えるため (ほぼ) 制限がありません。(最大で -10 億年 ~ +10 億年ぐらいの年月日)
import java.time.LocalDate;
import java.time.temporal.JulianFields;

// LocalDate を使った MJD : グレゴリオ年月日 → MJD
LocalDate date1 = LocalDate.of(2023,10,10);
long mjd1 = date1.getLong(JulianFields.MODIFIED_JULIAN_DAY);               // MJD へ変換する。
System.out.printf("date1 %d-%d-%d: %d\n", date1.getYear(), date1.getMonthValue(), date1.getDayOfMonth(), mjd1);  // 結果を表示する。

// LocalDate を使った MJD : MJD → グレゴリオ年月日
long mjd2 = 60227 - 10950;             // 49277: 2023-10-10 の 10950 日前
LocalDate setter = LocalDate.MIN;      // MIN / MAX どちらでも使用可。
LocalDate date2 = setter.with(JulianFields.MODIFIED_JULIAN_DAY, mjd2);     // LocalDate へ変換する。
System.out.printf("date2 %d-%d-%d: %d\n", date2.getYear(), date2.getMonthValue(), date2.getDayOfMonth(), mjd2);  // 結果を表示する。


実行結果 date1 2023-10-10: 60227 date2 1993-10-17: 49277

扱える範囲は -999999999-01-01 ~ +999999999-12-31
import java.time.LocalDate;

System.out.println(LocalDate.MIN);
System.out.println(LocalDate.MAX);


実行結果 -999999999-01-01 +999999999-12-31


日付の加減算に関する問題

問題は省略します。
Java のプログラムを扱っている人なら、日付計算の煩雑さも理解しているはずなので。

気になる人は、Python 版十進 BASIC 版を参照してください。


Java で実装

アルゴリズムは Wikipedia からのパクリです。

Mjd.java
import static java.lang.Math.floor;

/*
 * Mjd.java version 1.0 written by fuku@rouge.gr.jp
 *
 * 修正ユリウス日 / グレゴリオ暦 の相互変換を行う。
 *
 * https://ja.wikipedia.org/wiki/ユリウス通日#修正ユリウス日(MJD)
 * より。
 */


public class Mjd { /** * グレゴリオ暦 Y,M,D → MJD の変換 * @param y 年 * @param m 月 * @param d 日 * @return MJD の値 */ public static double greg2mjd(int y, int m, float d) { if(m <= 2) { m += 12; y -= 1; } return floor((365 + 1/4.0) * y) + floor(y / 400.0) - floor(y / 100.0) + floor(30.59 * (m - 2)) + d - 678912; }
/** * ユリウス暦 → MJD の変換 * @param y 年 * @param m 月 * @param d 日 * @return MJD の値 */ public static double jd2mjd(int y, int m, float d) { if(m <= 2) { m += 12; y -= 1; } return floor(365.25 * y) + floor(30.59 * (m-2)) + d - 678914; }
/** * MJD → ユリウス暦 の変換 * @param days MJD の値 * @return y,m,d ユリウス暦 */ public static double[] mjd2jd(double days) { double n = days + 678883; double a = 4 * n + 3; double b = 5 * floor((a % 1461) / 4) + 2; double y = floor(a / 1461); double m = floor(b / 153) + 3; double d = floor((b % 153) / 5) + 1; if(m > 12) { m -= 12; y += 1; } return new double[]{y,m,d}; }
/** * MJD → グレゴリオ暦 の変換 * @param days MJD の値 * @return y,m,d グレゴリオ暦 */ public static double[] mjd2greg(double days) { double n = days + 678881; double a = 4 * n + 3 + 4 * floor(3 / 4.0 * floor(4 * (n + 1) / 146097 + 1)); double b = 5 * floor((a % 1461) / 4) + 2; double y = floor(a / 1461); double m = floor(b / 153) + 3; double d = floor((b % 153) / 5) + 1; if(m > 12) { m -= 12; y += 1; } return new double[]{y,m,d}; }
/** * MJD → 曜日 の変換 * @param days MJD の値 * @return 曜日 (0:水曜 1:木曜 .. 6:火曜) */ public static double mjd2week(double days) { return days % 7; }
/** * MJD → 十二支 の変換 * @param days MJD の値 * @return 十二支 (0:寅 1:卯 2:辰 .. 11:丑) */ public static double mjd2zodiac(double days) { return days % 12; }
/** * MJD → 十干 の変換 * @param days MJD の値 * @return 十干 (0:甲 1:乙 2:丙 .. 9:癸) */ public static double mjd2stems(double days) { return days % 10; } }