前回同様、Wikipediaの計算式を元に修正ユリウス日から年月日の変換を行います。ユリウス日から修正ユリウス日を求めるには2400000.5を引くだけですので、今回は割愛することにしました。
それではまず、修正ユリウス日からグレゴリオ歴の年月日を求める関数を実装します。
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | std::tuple<int, int, int> mjd_to_gregorian(double mjd) {   auto n = mjd + 678881;   auto a = 4*n + 3 + 4*std::floor(3.0/4*std::floor(4*(n + 1)/146097 + 1));   auto b = 5*std::floor(std::fmod(a, 1461)/4) + 2;   int y = static_cast<int>(std::floor(a/1461));   int m = static_cast<int>(std::floor(b/153) + 3);   int d = static_cast<int>(std::floor(std::fmod(b, 153)/5) + 1);   if (m > 12)   {     ++y;     m -= 12;   }   return { y, m, d }; } | 
基本的にはWikipediaの式の通りですが、1月と2月が前年の13月と14月という形で結果が出ますので、最後に補正を行っています。前回同様、1月は1なので注意が必要です。
結果の型にはstd::tupleを使いました。前から順に、年、月、日が格納されます。こうしておけば、C++17以降にはなりますが、次のように書けるので便利です。
| 0 1 2 | auto [y, m, d] = mjd_to_julian(mjd); | 
それでは引き続き、修正ユリウス日からユリウス暦の年月日を求める関数を実装します。
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | std::tuple<int, int, int> mjd_to_julian(double mjd) {   auto n = mjd + 678883;   auto a = 4*n + 3;   auto b = 5*std::floor(std::fmod(a, 1461)/4) + 2;   int y = static_cast<int>(std::floor(a/1461));   int m = static_cast<int>(std::floor(b/153) + 3);   int d = static_cast<int>(std::floor(std::fmod(b, 153)/5) + 1);   if (m > 12)   {     ++y;     m -= 12;   }   return { y, m, d }; } | 
計算式が変わっただけで、それ以外は同じです。






