モジュール:ヨーグレキ

2年1月33日 (来) 22:21時点におけるYuito (トーク | 投稿記録)による版 (他モジュールから使いたくなった)

2つの関数を使用できます。

関数名 引数1 引数2 引数3 引数4 出力 使用例
gregorianToYogurian グレゴリオ暦における年 グレゴリオ暦における月 グレゴリオ暦における日 出力のフォーマット ヨーグレキのテーブル *{{#invoke:ヨーグレキ|gregorianToYogurian|2021|12|25|%d-%d-%d}}: 2-2-20[1]
yogurianToGregorian ヨーグレキにおける年 ヨーグレキにおける月 ヨーグレキにおける日 出力のフォーマット グレゴリオ暦のテーブル *{{#invoke:ヨーグレキ|yogurianToGregorian|11|1|1|%d-%d-%d}}: 2030/11/1[2]

  1. ソヴィエト崩壊30周年記念日だ!!
  2. 10周年記念日だ!!
local p = {}
MONTH_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

local function isLeap(year)
    return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)
end

local function leapdays(y1, y2)
    y1 = y1 - 1
    y2 = y2 - 1
    return (math.floor(y2 / 4) - math.floor(y1 / 4)) - (math.floor(y2 / 100) - math.floor(y1 / 100)) +
               (math.floor(y2 / 400) - math.floor(y1 / 400))
end

local function isValidDate(gYear, gMonth, gDay)
    return gMonth > 0 and gMonth <= 12 and gDay > 0 and gDay <=
               (MONTH_DAYS[gMonth] + ((gMonth == 2 and isLeap(gYear)) and 1 or 0))
end

local function isYogurianValidDate(yYear, yMonth, yDay)
    return yMonth > 0 and yMonth <= 12 and yDay > 0 and yDay <= 30 +
               (yMonth == 1 and (isLeap(yYear + 2020) and 6 or 5) or 0)
end

local function checkValidDate(gYear, gMonth, gDay)
    if not isValidDate(gYear, gMonth, gDay) then
        error(string.format("Date %d-%d-%d is invalid.", gYear, gMonth, gDay))
    end
end

local function checkYogurianValidDate(yYear, yMonth, yDay)
    if not isYogurianValidDate(yYear, yMonth, yDay) then
        error(string.format("Yogurian date %d-%d-%d is invalid.", yYear, yMonth, yDay))
    end
end

local function ddCalculate(y1, m1, d1, y2, m2, d2)
    yd = y2 - y1
    dd = yd * 365 + leapdays(y1, y2 + 1)
    if isLeap(y1) then
        if m1 > 2 then
            dd = dd - 1
        end
    end
    if isLeap(y2) and y1 < y2 then
        if m2 < 3 then
            dd = dd - 1
        end
    end
    for mi = 1, m2 - 1 do
        dd = dd + MONTH_DAYS[mi]
    end
    for mi = 1, m1 - 1 do
        dd = dd - MONTH_DAYS[mi]
    end
    dd = dd + d2 - d1
    return dd
end

local function gregorianToYogurian(gYear, gMonth, gDay)
    checkValidDate(gYear, gMonth, gDay)
    isLeapB = isLeap(gYear + (gMonth >= 11 and 1 or 0))
    d = ddCalculate(2020, 11, 1, gYear, gMonth, gDay)
    yy = gYear - 2019 - (gMonth >= 11 and 0 or 1)
    dfn = d - 365 * (yy - 1) - leapdays(2021, gYear + (gMonth >= 11 and 1 or 0)) + 1
    hmd = isLeapB and 36 or 35
    ym = dfn <= hmd and 1 or math.floor((dfn - hmd - 1) / 30) + 2
    yd = ym == 1 and dfn or (dfn - hmd - 1) % 30 + 1
    return {yy, ym, yd}
end

local function yogurianToGregorian(yYear, yMonth, yDay)
    checkYogurianValidDate(yYear, yMonth, yDay)
    isLeapB = isLeap(yYear + 2020)
    gDay = yMonth == 1 and yDay or (yMonth - 2) * 30 + (isLeapB and 36 or 35) + yDay
    gYear = yYear + 2019 + (gDay > 61 and 1 or 0)
    gMonth = 11
    while true do
        gMonth = gMonth - (gMonth > 12 and 12 or 0)
        monthDay = MONTH_DAYS[gMonth] + ((isLeapB and gMonth == 2) and 1 or 0)
        if gDay <= monthDay then
            break
        end
        gDay = gDay - monthDay
        gMonth = gMonth + 1
    end
    return {gYear, gMonth, gDay}
end

local function wikiGregorianToYogurian(frame)
	yDate = gregorianToYogurian(tonumber(frame.args[1]),tonumber(frame.args[2]),tonumber(frame.args[3]))
	return string.format(frame.args[4],yDate[1],yDate[2],yDate[3])
end

local function wikiYogurianToGregorian(frame)
	gDate = yogurianToGregorian(tonumber(frame.args[1]),tonumber(frame.args[2]),tonumber(frame.args[3]))
	return string.format(frame.args[4],gDate[1],gDate[2],gDate[3])
end

p.gregorianToYogurianL = gregorianToYogurian
p.yogurianToGregorianL = yogurianToGregorian

p.gregorianToYogurian = wikiGregorianToYogurian
p.yogurianToGregorian = wikiYogurianToGregorian

return p