#!/usr/bin/env node /** * Wrapper / Age Calculator * Usage: * node umurku.js 2000-05-15 * node umurku.js 15/05/2000 * node umurku.js 2000-05-15 --json */ import { parseArgs } from 'node:util'; // ====================== HELPER ====================== function parseDate(input) { if (!input) throw new Error('Tanggal lahir wajib diisi'); // Support: YYYY-MM-DD | DD/MM/YYYY | DD-MM-YYYY let year, month, day; if (input.includes('-') && input.split('-')[0].length === 4) { // YYYY-MM-DD [year, month, day] = input.split('-').map(Number); } else if (input.includes('/') || input.includes('-')) { // DD/MM/YYYY atau DD-MM-YYYY const parts = input.replace(/-/g, '/').split('/'); [day, month, year] = parts.map(Number); } else { throw new Error('Format tanggal tidak dikenali. Gunakan YYYY-MM-DD atau DD/MM/YYYY'); } const d = new Date(year, month - 1, day); if (isNaN(d.getTime()) || d.getDate() !== day) { throw new Error('Tanggal tidak valid'); } return d; } function getMonthDiff(d1, d2) { let months = (d2.getFullYear() - d1.getFullYear()) * 12; months -= d1.getMonth(); months += d2.getMonth(); return months <= 0 ? 0 : months % 12; } function getDayName(date) { return date.toLocaleDateString('id-ID', { weekday: 'long' }); } function getZodiac(month, day) { const zodiacs = [ { name: 'Capricorn', start: [12, 22], end: [1, 19] }, { name: 'Aquarius', start: [1, 20], end: [2, 18] }, { name: 'Pisces', start: [2, 19], end: [3, 20] }, { name: 'Aries', start: [3, 21], end: [4, 19] }, { name: 'Taurus', start: [4, 20], end: [5, 20] }, { name: 'Gemini', start: [5, 21], end: [6, 20] }, { name: 'Cancer', start: [6, 21], end: [7, 22] }, { name: 'Leo', start: [7, 23], end: [8, 22] }, { name: 'Virgo', start: [8, 23], end: [9, 22] }, { name: 'Libra', start: [9, 23], end: [10, 22] }, { name: 'Scorpio', start: [10, 23], end: [11, 21] }, { name: 'Sagittarius', start: [11, 22], end: [12, 21] }, ]; for (const z of zodiacs) { const [sm, sd] = z.start; const [em, ed] = z.end; if ((month === sm && day >= sd) || (month === em && day <= ed)) { return z.name; } } return 'Capricorn'; } function nextBirthday(birth, now) { let next = new Date(now.getFullYear(), birth.getMonth(), birth.getDate()); if (next < now) { next = new Date(now.getFullYear() + 1, birth.getMonth(), birth.getDate()); } const diffMs = next - now; const daysLeft = Math.ceil(diffMs / (1000 * 60 * 60 * 24)); return { tanggal: next.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' }), sisa_hari: daysLeft, }; } // ====================== CORE CALCULATOR ====================== export function hitungUmur(tanggalLahirInput, tanggalAcuan = new Date()) { const tglLahir = parseDate(tanggalLahirInput); const sekarang = new Date(tanggalAcuan); if (sekarang - tglLahir < 0) { throw new Error('Tanggal lahir tidak boleh melebihi tanggal acuan!'); } // --- Logika sama persis dengan umurku.com --- let tahun = sekarang.getFullYear() - tglLahir.getFullYear(); let bulan = getMonthDiff(tglLahir, sekarang); let hari = sekarang.getDate() - tglLahir.getDate(); if (hari < 0) { bulan--; const bulanLalu = new Date(sekarang.getFullYear(), sekarang.getMonth(), 0).getDate(); hari += bulanLalu; } if (bulan < 0) { tahun--; bulan += 12; } const selisihMs = sekarang - tglLahir; const totalDetik = Math.floor(selisihMs / 1000); const totalMenit = Math.floor(totalDetik / 60); const totalJam = Math.floor(totalMenit / 60); const totalHari = Math.floor(totalJam / 24); const next = nextBirthday(tglLahir, sekarang); return { tanggal_lahir: tglLahir.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric', }), hari_lahir: getDayName(tglLahir), zodiak: getZodiac(tglLahir.getMonth() + 1, tglLahir.getDate()), tanggal_acuan: sekarang.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric', }), umur: { tahun, bulan, hari, }, total: { hari: totalHari, jam: totalJam, menit: totalMenit, detik: totalDetik, }, ulang_tahun_berikutnya: next, teks: `Pada hari ini, tanggal ${sekarang.toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric', })}, umur kita adalah: ${tahun} Tahun, ${bulan} Bulan, ${hari} Hari`, }; } // ====================== CLI ====================== if (import.meta.url === `file://${process.argv[1]}`) { try { const { values, positionals } = parseArgs({ allowPositionals: true, options: { json: { type: 'boolean', short: 'j', default: true }, help: { type: 'boolean', short: 'h' }, }, }); if (values.help || positionals.length === 0) { console.log(` Penggunaan: node umurku.js [--json] Contoh: node umurku.js 2000-05-15 node umurku.js 15/05/2000 node umurku.js 2000-05-15 --json `); process.exit(0); } const hasil = hitungUmur(positionals[0]); console.log(JSON.stringify(hasil, null, 2)); } catch (err) { console.error(JSON.stringify({ error: err.message }, null, 2)); process.exit(1); } }