モジュール:MJD
表示
モジュールの解説[作成]
local p = {}
-- os.date() が UTC で返されるので UTC+9 に変換
function p.curmjd()
return math.floor((os.time() / 3600 + 9) / 24) + 40587
end
function p.curymd()
return p.mjd2ymd({p.curmjd()})
end
function p.ymd2mjd(args)
local y = tonumber(args[1])
local m = tonumber(args[2])
local d = tonumber(args[3])
local mode = args.mode
-- グレゴリオ暦→修正ユリウス日(MJD)
y = y + math.floor((m - 3) / 12) -- 1月と2月は前年扱い
m = (m - 3) % 12 + 3 -- 1月→13月、2月→14月
-- 1年ごとに365日ずつずらす。ただし閏日が4年に1度挿入され、100年に1度挿入されず、400年に1度挿入される
-- 1か月を30.6日として整数倍し小数切り捨てて、3月からの日数[31,30,31,30,31][31,30,31,30,31][31]を生成。2月は最後なので処理不要
local n = 365 * y + math.floor(y / 4) - math.floor(y / 100) + math.floor(y / 400) + math.floor(30.6 * m + 0.7) + d - 678974
repeat
-- -100840 = 1582年10月15日, pg: 遡及グレゴリオ暦
if n >= -100840 or mode == 'pg' then break end
-- 1582年10月4日以前はユリウス暦を適用(1582年10月5日 - 14日は存在しない)
n = n + math.floor(y / 100) - math.floor(y / 400) - 2
-- pj: 遡及ユリウス暦
if y >= 0 or mode == 'pj' then break end
-- 紀元前1年2月28日以前は閏日を挿入しない(紀元前1年2月29日は存在しない)
n = n - math.floor(y / 4)
--
if y >= -7 then break end
-- 紀元前8年2月29日以前は3年に1度閏日を挿入する
n = n + math.floor((y + 1) / 3) + 2
-- -695015 = 紀元前45年1月1日
if n >= -695015 or mode == 'pg' then break end
-- 紀元前46年以前はユリウス暦未実施
n = nil
until true -- ループ強制脱出(breakを使用するため)
return n
end
function p.mjd2ymd(args)
local n = tonumber(args[1])
local mode = args.mode or 'b'
local y
-- -100840 = 1582年10月15日, pg: 遡及グレゴリオ暦
if n >= -100840 or mode == 'pg' then
-- 修正ユリウス日(MJD)→グレゴリオ暦
n = n + 678881 -- グレゴリオ暦0年3月1日を0とする
-- 100年ずつ[36524,36524,36524,36525][36524,36524,36524,36525]...と分解
local y100 = math.floor((n + 0.9) / 36524.25) -- 年の100の位以上
n = n - math.floor(36524.25 * y100) -- (100*y100)年3月1日を0とする
-- 1年ずつ[365,365,365,366][365,365,365,366]...と分解
-- 最後の1年は3/4の確率で365日だが、最後なので処理不要
y = math.floor((n + 0.9) / 365.25) -- 年の1の位と10の位
n = n - math.floor(365.25 * y) -- 各年3月1日を0とする
y = 100*y100 + y
-- -678883 = 紀元前1年3月1日, pj: 遡及ユリウス暦
elseif n >= -678883 or mode == 'pj' then
-- 修正ユリウス日(MJD)→ユリウス暦
n = n + 678883 -- ユリウス暦0年3月1日を0とする
-- 1年ずつ[365,365,365,366][365,365,365,366]...と分解
y = math.floor((n + 0.9) / 365.25) -- 年の全桁
n = n - math.floor(365.25 * y) -- 各年3月1日を0とする
-- -681438 = 紀元前8年3月1日
elseif n >= -681438 then
-- 修正ユリウス日(MJD)→閏日なしの暦
n = n + 678883 -- 閏日なしの暦0年3月1日を0とする
-- 1年ずつ[365][365][365][365]...と分解
y = math.floor((n + 0.9) / 365) -- 年の全桁
n = n - math.floor(365 * y) -- 各年3月1日を0とする
-- -695015 = 紀元前45年1月1日
elseif n >= -695015 then
-- 修正ユリウス日(MJD)→3年に1度閏日を挿入した暦
n = n + 679246 -- 3年に1度閏日を挿入した暦"-1年"3月1日を0とする
-- 1年ずつ[365,365,366][365,365,366]...と分解
y = math.floor((n + 0.9) / (365 + 1/3)) -- 年の全桁
n = n - math.floor((365 + 1/3) * y) -- 各年3月1日を0とする
y = y - 1 -- 基準を0年に戻す
else
n = nil
end
if n then
-- 1か月ずつ[31,30,31,30,31][31,30,31,30,31][31]と分解。2月は最後なので処理不要
local m = math.floor((n + 92.3) / 30.6)
local d = math.floor(n + 93.3 - 30.6 * m)
y = y + math.floor((m - 1) / 12) -- 前年扱いの1月と2月を元に戻す
m = (m - 1) % 12 + 1 -- 1月←13月、2月←14月
return {y, m, d}
else
return nil
end
end
return p