sourcehypertextpubliccalendricalcal.js

import attic from "/calendrical/attic.js";

const greekNums = (
	num,
	caps = false,
	stigma = 0,
	qoppa = 0,
	indicator = "keraia"
) => {
	let digits = [
		["", "α", "β", "γ", "δ", "ε", ["ϝ", "ϛ", "στ"][stigma], "ζ", "η", "θ"],
		["", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", ["ϟ", "ϙ"][qoppa]],
		["", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "ϡ"]
	];

	let output = "";
	for (let idx = Math.floor(Math.log10(num)); idx >= 0; idx--) {
		const placeValue = Math.floor(num / 10 ** idx) % 10;
		if (placeValue == 0) continue;
		output += "͵".repeat(Math.floor(idx / 3)) + digits[idx % 3][placeValue];
	}
	if (caps) {
		output = output.toUpperCase();
	}
	if (indicator == "keraia") {
		output = `${output}ʹ`;
	}
	if (indicator == "vinculum") {
		output = `<span class="overline">${output}</span>`;
	}
	return output;
};

const formatting = {
	months: {
		enLatinate: {
			long: [
				"Hecatombæon",
				"Metageitnion",
				"Boedromion",
				"Pyanepsion",
				"Mæmacterion",
				"Poseideon",
				"Poseideon II",
				"Gamelion",
				"Anthesterion",
				"Elaphebolion",
				"Mounychion",
				"Thargelion",
				"Scirophorion"
			],
			short: [
				"Heca.",
				"Met.",
				"Boe.",
				"Pya.",
				"Mæ.",
				"Pos.",
				"Pos. II",
				"Gam.",
				"Anth.",
				"Ela.",
				"Mou.",
				"Thar.",
				"Sci."
			]
		},
		enLiteral: {
			long: [
				"Hekatombaiōn",
				"Metageitniōn",
				"Boēdromiōn",
				"Pyanepsiōn",
				"Maimaktēriōn",
				"Poseideōn",
				"Poseideōn II",
				"Gamēliōn",
				"Anthestēriōn",
				"Elaphēboliōn",
				"Mounykhiōn",
				"Thargēliōn",
				"Skirophoriōn"
			],
			short: [
				"Heka.",
				"Met.",
				"Boē.",
				"Pya.",
				"Mai.",
				"Pos.",
				"Pos. II",
				"Gam.",
				"Anth.",
				"Ela.",
				"Mou.",
				"Thar.",
				"Sci."
			]
		},
		grc: {
			long: [
				"Ἑκατομβαιῶνος",
				"Μεταγειτνιῶνος",
				"Βοηδρομιῶνος",
				"Πυανεψιῶνος",
				"Μαιμακτηριῶνος",
				"Ποσειδεῶνος",
				"Ποσειδεῶνος Βʹ",
				"Γαμηλιῶνος",
				"Ἀνθεστηριῶνος",
				"Ἐλαφηβολιῶνος",
				"Μουνυχιῶνος",
				"Θαργηλιῶνος",
				"Σκιροφοριῶνος"
			],
			short: [
				"Ἐκα.",
				"Μετ.",
				"Βοη.",
				"Πυα.",
				"Μαι.",
				"Ποσ.",
				"Ποσ. βʹ",
				"Γαμ.",
				"Ἀνθ.",
				"Ἐλα.",
				"Μου.",
				"Θαρ.",
				"Σκι."
			]
		}
	},
	olympiadIndicator: {
		en: "Ol.",
		nl: "ol.",
		grc: "Ὀλ."
	},
	weekdays: ["☉", "☽", "♂", "☿", "♃", "♀", "♄"],
	template: {
		en: (day, month, year, olympiad) =>
			`${day} ${month} ${olympiad}.${year}`
	}
};

const formatDate = (date, options) => {
	const isGreek = options.numSystem == "greek";
	const numSettings = [
		options.capNums,
		+options.stigma,
		+options.qoppa,
		options.numInd
	];

	const rawDayPart =
		options.daySystem == "signed"
			? Math.abs(date.signedDate)
			: date.rawDate;
	let dayPart = isGreek
		? greekNums(rawDayPart, ...numSettings)
		: `${rawDayPart}`;
	if (options.daySystem == "signed") {
		if (date.signedDate == 0) {
			dayPart = "ἑ.κ.ν.";
		} else if (date.signedDate < 0) {
			dayPart = `${dayPart}☾`;
		}
	}

	const monthPart =
		formatting.months[options.monthNames][
			options.shortMonths ? "short" : "long"
		][date.month];

	const yearPart = isGreek
		? greekNums(date.year, ...numSettings)
		: `${date.year}`;

	let olPart = isGreek
		? greekNums(date.olympiad, ...numSettings)
		: `${date.olympiad}`;
	if (options.olInd) {
		olPart = `${
			formatting.olympiadIndicator[
				options.monthNames == "grc" ? "grc" : options.lang
			]
		} ${olPart}`;
	}

	let output = formatting.template[options.lang](
		dayPart,
		monthPart,
		yearPart,
		olPart
	);
	if (options.weekdays) {
		output = `${output} ${formatting.weekdays[date.weekday]}`;
	}

	return output;
};

const convert = () => {
	if ($("#conv-numSystem").value == "greek") {
		$$(".greek-only input, .greek-only select").forEach(el => {
			el.removeAttribute("disabled");
		});
	} else {
		$$(".greek-only input, .greek-only select").forEach(el => {
			el.setAttribute("disabled", true);
		});
	}

	const data = Object.fromEntries(new FormData($("#calendar-converter")));

	const isoDate = `${data.gregYear.padStart(
		4,
		"0"
	)}-${data.gregMonth.padStart(2, "0")}-${data.gregDay.padStart(
		2,
		"0"
	)}T12:00:00.000Z`;

	$("#conv-atticDate").innerHTML = formatDate(attic(isoDate), data);
};

documentReady(() => {
	const rightNow = new Date();

	$("#conv-gregDay").value = rightNow.getDate();
	$("#conv-gregMonth").value = rightNow.getMonth() + 1;
	$("#conv-gregYear").value = rightNow.getFullYear();

	$("#calendar-converter").on("change", () => {
		convert();
	});
	convert();
});