import os, datetime
import customtkinter as ctk
from skyfield.api import Loader
from skyfield import almanac
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
BULAN_MASEHI = ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"]
BULAN_HIJRIAH = ["Muharam", "Safar", "Rabiulawal", "Rabiulakhir", "Jumadilawal", "Jumadilakhir", "Rajab", "Syakban", "Ramadan", "Syawal", "Zulkaidah", "Zulhijah"]
class Menu13App(ctk.CTk):
def __init__(self):
super().__init__()
self.title("Konversi Kalender KHGT (Modul 13)")
self.geometry("700x500")
ctk.set_appearance_mode("Dark")
self.load_obj = Loader(BASE_DIR)
self.eph = self.load_obj('de421.bsp')
self.ts = self.load_obj.timescale()
self.setup_ui()
def setup_ui(self):
self.sidebar = ctk.CTkFrame(self, width=250)
self.sidebar.pack(side="left", fill="y", padx=10, pady=10)
now = datetime.datetime.now()
self.radio_var = ctk.StringVar(value="m2h")
ctk.CTkRadioButton(self.sidebar, text="Masehi -> Hijriah", variable=self.radio_var, value="m2h", command=self.update_ui).pack(pady=5)
ctk.CTkRadioButton(self.sidebar, text="Hijriah -> Masehi", variable=self.radio_var, value="h2m", command=self.update_ui).pack(pady=5)
self.entry_d = ctk.CTkEntry(self.sidebar); self.entry_d.insert(0, str(now.day)); self.entry_d.pack(pady=5)
self.combo_m = ctk.CTkOptionMenu(self.sidebar, values=BULAN_MASEHI); self.combo_m.pack(pady=5)
self.entry_y = ctk.CTkEntry(self.sidebar); self.entry_y.insert(0, str(now.year)); self.entry_y.pack(pady=5)
self.combo_adj = ctk.CTkOptionMenu(self.sidebar, values=["-2", "-1", "0", "+1", "+2"]); self.combo_adj.set("0"); self.combo_adj.pack(pady=5)
ctk.CTkButton(self.sidebar, text="▶ KONVERSI", command=self.hitung).pack(pady=15)
self.textbox = ctk.CTkTextbox(self, font=("Consolas", 14))
self.textbox.pack(side="right", fill="both", expand=True, padx=10, pady=10)
def update_ui(self):
if self.radio_var.get() == "m2h": self.combo_m.configure(values=BULAN_MASEHI)
else: self.combo_m.configure(values=BULAN_HIJRIAH)
def get_approx_nm_tt(self, y, m):
abs_month = (y - 1) * 12 + m
return 2451550.0 + (abs_month - 17038) * 29.530588853
def get_hijri_month(self, tt_float):
abs_m = 17038 + round((tt_float - 2451550.0) / 29.530588853)
return (abs_m - 1) // 12 + 1, (abs_m - 1) % 12 + 1
def calc_khgt_1st(self, nm_tt):
t_nm = self.ts.tt_jd(nm_tt)
y, m, d, h, _, _ = t_nm.utc
t_mid = self.ts.utc(y, m, d)
return t_mid.tt + 1.0 if h < 15 else t_mid.tt + 2.0
def hitung(self):
self.textbox.delete("1.0", "end")
mode = self.radio_var.get()
d, y = int(self.entry_d.get()), int(self.entry_y.get())
m_str = self.combo_m.get()
adj = int(self.combo_adj.get())
try:
if mode == "m2h":
m = BULAN_MASEHI.index(m_str) + 1
t_target = self.ts.utc(y, m, d).tt
t0, t1 = self.ts.tt_jd(t_target - 35.0), self.ts.tt_jd(t_target + 2.0)
t_ph, y_ph = almanac.find_discrete(t0, t1, almanac.moon_phases(self.eph))
nms = [t.tt for t, p in zip(t_ph, y_ph) if p == 0]
curr_nm = None
for nm in reversed(nms):
if t_target >= self.calc_khgt_1st(nm) - 0.1:
curr_nm = nm
break
hy, hm = self.get_hijri_month(curr_nm)
start_tt = self.calc_khgt_1st(curr_nm)
hd = int(round(t_target - start_tt)) + 1 + adj
self.textbox.insert("end", f"Hasil Konversi (KHGT):\n>> {hd} {BULAN_HIJRIAH[hm-1]} {hy} H\n")
else:
m = BULAN_HIJRIAH.index(m_str) + 1
approx_tt = self.get_approx_nm_tt(y, m)
t0, t1 = self.ts.tt_jd(approx_tt - 5.0), self.ts.tt_jd(approx_tt + 5.0)
t_ph, y_ph = almanac.find_discrete(t0, t1, almanac.moon_phases(self.eph))
nm_tt = [t.tt for t, p in zip(t_ph, y_ph) if p == 0][0]
start_tt = self.calc_khgt_1st(nm_tt)
t_res = self.ts.tt_jd(start_tt + (d - 1) - adj)
ry, rm, rd, _, _, _ = t_res.utc
self.textbox.insert("end", f"Hasil Konversi Masehi:\n>> {int(rd)} {BULAN_MASEHI[int(rm)-1]} {int(ry)} M\n")
except Exception as e:
self.textbox.insert("end", f"Error: {e}")
if __name__ == "__main__":
app = Menu13App()
app.mainloop()