Module:Sandbox/HenryLi
local getArgs = require('Module:Arguments').getArgs
local dateUtils = {}
local year = {
--1 2 3 4 5 6 7 8 9 10 11 12 13
--[2460351] = { name = "甲辰", months = { 29, 30, 29, 29, 30, 29, 30, 30, 29, 30, 30, 29 }, intercalary = 0 },
[2460705] = { name = "乙巳", months = { 30, 29, 30, 29, 29, 30, 29, 30, 29, 30, 30, 30, 29 }, intercalary = 6 },
[2461089] = { name = "丙午", months = { 30, 29, 30, 29, 29, 30, 29, 29, 30, 30, 30, 29 }, intercalary = 0 },
}
local sb60 = {
"甲子", "乙丑", "丙寅", "丁卯", "戊辰", "己巳", "庚午", "辛未", "壬申", "癸酉",
"甲戌", "乙亥", "丙子", "丁丑", "戊寅", "己卯", "庚辰", "辛巳", "壬午", "癸未",
"甲申", "乙酉", "丙戌", "丁亥", "戊子", "己丑", "庚寅", "辛卯", "壬辰", "癸巳",
"甲午", "乙未", "丙申", "丁酉", "戊戌", "己亥", "庚子", "辛丑", "壬寅", "癸卯",
"甲辰", "乙巳", "丙午", "丁未", "戊申", "己酉", "庚戌", "辛亥", "壬子", "癸丑",
"甲寅", "乙卯", "丙辰", "丁巳", "戊午", "己未", "庚申", "辛酉", "壬戌", "癸亥"
}
local m12 = {
"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"
}
local d30 = {
"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
"十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
"廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十", "卅一"
}
local makeNow = function()
local d = os.date("*t", os.time())
return os.time {year = d.year, month = d.month, day = d.day} -- + 8 * 60 * 60 -- data based on UTC+8
end
local makeTime = function(Y, M, D)
return os.time {year = Y, month = M, day = D}
end
local makeAjd = function(t)
return math.floor((t / 86400) + 2440587.5)
end
dateUtils.cdate = function(frame)
local Y = tonumber(frame.args.y) or 2025
local M = tonumber(frame.args.m) or 3
local D = tonumber(frame.args.d) or 1
local today = frame.args.today
local t
if today then
t = makeNow()
else
t = makeTime(Y, M, D)
end
local ajd_int = makeAjd(t)
local year_name = ''
local month_name = ''
local day_name = ''
local day_sb_name = ''
for i, year_data in pairs(year) do
local days = 0
for i,v in pairs(year_data.months) do
days = days + v
end
local year_start = i
local year_end = year_start + days
if ajd_int >= year_start and year_start < year_end then
local month_start = year_start
local month_end = 0
local month = 0
--local yy = (os.date("*t", os.date((year_start - 2440587.5 ) * 86400)).year - 4) % 60 + 1
for i, v in pairs(year_data.months) do
month = i
month_end = month_start + v
if ajd_int >= month_start and ajd_int < month_end then
year_name = year_data.name .. '年'
if month == year_data.intercalary + 1 then
month_name = "閏" .. m12[month - 1]
else
if month > year_data.intercalary + 1 then
month_name = m12[month - 1]
else
month_name = m12[month]
end
end
month_name = month_name .. '月'
local day = ajd_int - month_start + 1
day_name = d30[day]
local day_sb = ( ajd_int - 11) % 60 + 1
day_sb_name = sb60[day_sb]
break
else
month_start = month_start + v
end
end
break
else
end
end
local d = os.date("%Y-%m-%d ", t)
-- local d = os.date("%Y-%m-%d %H:%M:%S", t)
return d .. year_name .. month_name .. day_name .. day_sb_name
end
dateUtils.d60 = function(text)
local jd = tonumber(text.args[1])
local ajd = jd - 0.5
local ajd_int = math.floor(ajd)
local sb = ( ajd_int - 9 ) % 60
local sb60_x = sb60[sb]
return sb60_x
end
-- date_utils.lua
--[[
Lua Date & Calendar Utilities Module
------------------------------------
Provides:
- getJD(yyyy, mm, dd) → Julian Day at midnight UT
- NdaysGregJul(y) → Number of days in year (Julian/Gregorian)
- get_Western_calendar_name(y) → Calendar name by year
- langConstant(lang) → Language constants (0=English, 1=Traditional, 2=Simplified Chinese)
Usage:
local dateUtils = require("date_utils")
local jd = dateUtils.getJD(2025, 8, 16)
local days = dateUtils.NdaysGregJul(2024)
local calName = dateUtils.get_Western_calendar_name(2025)
local langData = dateUtils.langConstant(1) -- Traditional Chinese
--]]
--local dateUtils = {}
-------------------------------------------------
-- Julian Day Number Calculation
-------------------------------------------------
function dateUtils.getJD(yyyy, mm, dd)
local yy, m = yyyy, mm
if m <= 2 then
m = m + 12
yy = yy - 1
end
local ymd = 10000 * yy + 100 * m + dd
local B
if ymd <= 15821004 then
B = -2 + math.floor((yy + 4716) / 4) - 1179
else
B = math.floor(yy / 400) - math.floor(yy / 100) + math.floor(yy / 4)
end
return 365 * yy - 679004 + B + math.floor(30.6001 * (m + 1)) + dd + 2400000.5
end
-------------------------------------------------
-- Number of days in a Gregorian/Julian year
-------------------------------------------------
function dateUtils.NdaysGregJul(y)
local ndays = (y == 1582) and 355 or 365
if y % 4 == 0 then
ndays = ndays + 1
end
if y > 1582 then
if y % 100 == 0 then ndays = ndays - 1 end
if y % 400 == 0 then ndays = ndays + 1 end
end
return ndays
end
-------------------------------------------------
-- Calendar name by year
-------------------------------------------------
function dateUtils.get_Western_calendar_name(y)
if y > 1582 then
return {"額曆"}
elseif y == 1582 then
return {"儒曆額曆"}
elseif y > 7 then
return {"儒曆"}
else
return {"逆推儒曆"}
end
end
-------------------------------------------------
-- Language constants for calendar rendering
-------------------------------------------------
function dateUtils.langConstant(lang)
-- Chinese data
local gMonthChi = {"壹月","貳月","叄月","肆月","伍月","陸月","柒月","捌月","久月","拾月","拾壹月","拾貳月"}
local weeksChi = {"日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"}
local heavenChi = {"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"}
local earthChi = {"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"}
local animalChi = {"鼠","牛","虎","兔","龍","蛇","馬","羊","猴","雞","狗","豬"}
local animalSim = {"鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"}
local month_numChi = {"正","二","三","四","五","六","七","八","九","十","十一","十二"}
-- Generate Chinese lunar dates 初一..三十
local date_numChi = {"初一"}
for i=2,10 do table.insert(date_numChi,"初"..month_numChi[i]) end
table.insert(date_numChi,"十一")
for i=12,19 do table.insert(date_numChi,"十"..month_numChi[i-11]) end
table.insert(date_numChi,"二十")
table.insert(date_numChi,"廿一")
for i=22,29 do table.insert(date_numChi,"廿"..month_numChi[i-21]) end
table.insert(date_numChi,"三十")
local monthLChi = {"小","大"}
local QnamesChi = {"朔","上弦","望","下弦"}
local soltermNamesChi = {"小寒","大寒","立春","雨水","驚蟄","春分",
"清明","穀雨","立夏","小滿","芒種","夏至",
"小暑","大暑","立秋","處暑","白露","秋分",
"寒露","霜降","立冬","小雪","大雪","冬至","小寒"}
local note_earlyChi = "朔的時刻接近午夜零時,初一或會提早一天。"
local note_lateChi = "朔的時刻接近午夜零時,初一或會推遲一天。"
local note1929Chi = "注意。一九二九年以前朔日以北京時計算,遲東經百二度遲十四分鐘,因此列出朔時過了初二零時。"
local note1914Chi = "注意。一九一四年前朔計算方法不準確,且一九二九年前用北京時,遲東經百二度遲約十四分鐘。"
return {
gMonth = gMonthChi, weeks = weeksChi, lang = lang,
heaven = heavenChi, earth = earthChi, animal = animalChi,
region = "default", cmonth = month_numChi, monthL = monthLChi,
Qnames = QnamesChi, soltermNames = soltermNamesChi,
julian = false, li_ancient = nil,
date_numChi = date_numChi,
note_early = note_earlyChi, note_late = note_lateChi,
note1929 = note1929Chi, note1914 = note1914Chi
}
end
--------------------------------------------------
-- Convert kin number to month number & year offset
--------------------------------------------------
function dateUtils.kinToMonthYearoffset(kinIn, y, region)
local kin = math.abs(kinIn)
local yearOffset, monNum = 0, kin
-- Hon dynasty
if y < -103 and kin > 9 then
yearOffset = 1
end
-- Sun dynasty
if y == 8 and kin == 12 then
monNum, yearOffset = 1, 1
elseif y > 8 and y < 23 then
monNum = (kin == 12) and 1 or (kin + 1)
if kin == 12 then yearOffset = 1 end
elseif y == 23 and kin < 12 then
monNum = kin + 1
end
-- Ngai dynasty
if ((y == 237 and kin > 2) or (y == 238) or (y == 239 and kin < 12)) and region == "default" then
monNum = (kin == 12) and 1 or (kin + 1)
if kin == 12 then yearOffset = 1 end
end
-- Tang dynasty
if y > 688 and y < 700 then
if kin > 10 then yearOffset = 1 end
elseif y == 761 and kin > 10 then
monNum, yearOffset = kin - 10, 1
elseif y == 762 and kin < 4 then
monNum = kin + 2
end
if kinIn < 0 then
monNum = -monNum
end
return { monNum = monNum, yearOffset = yearOffset }
end
-- ===========================================================================
-- Determine first month number for a year
-- ===========================================================================
function dateUtils.firstMonthNum(y)
local firstMonth = 1
if y < -102 then
firstMonth = 10
elseif y > 689 and y < 701 then
firstMonth = 11
end
return firstMonth
end
-- ===========================================================================
-- Decompress time values encoded with compression algorithm
-- Compression: t = floor(x) * 1441 + m
-- Inverse: x ≈ floor(t/1441) + (t - floor(t/1441)*1441)/1440
-- ===========================================================================
function dateUtils.decompress_time(t)
local x = {}
for i = 1, #t do
local y = math.floor(t[i] / 1441)
local m = t[i] - 1441 * y
if m > 1439.5 then
m = 1439.9
end
table.insert(x, y + m / 1440.0)
end
return x
end
-- Returns offsets for solar and lunar calculations
function dateUtils.offset_sunMoon()
return {solar = 5, lunar = 5}
end
return dateUtils
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.