🎂 Age Calculator exact · zodiac · milestones

Calculate exact age in years, months, days — plus fun facts and upcoming milestones
const asOfDateInput = document.getElementById('asOfDate'); const todayBtn = document.getElementById('todayBtn'); const swapBtn = document.getElementById('swapBtn'); const calculateBtn = document.getElementById('calculateBtn'); const presetBtns = document.querySelectorAll('[data-preset]'); // Result spans const ageYearsSpan = document.getElementById('ageYears'); const ageDetailSpan = document.getElementById('ageDetail'); const totalMonthsSpan = document.getElementById('totalMonths'); const totalWeeksSpan = document.getElementById('totalWeeks'); const totalDaysSpan = document.getElementById('totalDays'); // Fun facts const zodiacSign = document.getElementById('zodiacSign'); const birthstone = document.getElementById('birthstone'); const birthFlower = document.getElementById('birthFlower'); const birthDayOfWeek = document.getElementById('birthDayOfWeek'); // Birthday const nextBirthdayDate = document.getElementById('nextBirthdayDate'); const birthdayCountdown = document.getElementById('birthdayCountdown'); const milestoneList = document.getElementById('milestoneList'); // Life stats const heartbeatCount = document.getElementById('heartbeatCount'); const earthOrbits = document.getElementById('earthOrbits'); const sleepHours = document.getElementById('sleepHours'); // Set today's date as default for "as of" function setTodayAsOf() { const today = new Date(); const yyyy = today.getFullYear(); const mm = String(today.getMonth() + 1).padStart(2, '0'); const dd = String(today.getDate()).padStart(2, '0'); asOfDateInput.value = `${yyyy}-${mm}-${dd}`; } // Initialize with today setTodayAsOf(); // If DOB is empty, set a default if (!dobInput.value) { dobInput.value = '1990-01-01'; } // Calculate age function function calculateAge() { const dobStr = dobInput.value; const asOfStr = asOfDateInput.value; if (!dobStr || !asOfStr) { alert('Please select both dates'); return; } const dob = new Date(dobStr); const asOf = new Date(asOfStr); if (dob > asOf) { alert('Birth date cannot be after the "as of" date'); return; } // Calculate difference in years, months, days let years = asOf.getFullYear() - dob.getFullYear(); let months = asOf.getMonth() - dob.getMonth(); let days = asOf.getDate() - dob.getDate(); // Adjust for negative days if (days < 0) { months--; // Get last day of previous month const lastMonth=new Date(asOf.getFullYear(), asOf.getMonth(), 0); days=lastMonth.getDate() - dob.getDate() + asOf.getDate(); } // Adjust for negative months if (months < 0) { years--; months +=12; } // Update age displays ageYearsSpan.textContent=`${years} years`; ageDetailSpan.textContent=`${years} years, ${months} months, ${days} days`; // Calculate total days, weeks, months const diffTime=asOf - dob; const diffDays=Math.floor(diffTime / (1000 * 60 * 60 * 24)); const diffWeeks=Math.floor(diffDays / 7); const diffMonths=years * 12 + months; totalDaysSpan.textContent=diffDays.toLocaleString(); totalWeeksSpan.textContent=diffWeeks.toLocaleString(); totalMonthsSpan.textContent=diffMonths.toLocaleString(); // Fun facts based on birth date updateFunFacts(dob); // Next birthday and milestones updateBirthdayInfo(dob, asOf); // Life stats (approximate) updateLifeStats(years, diffDays); } // Update zodiac, birthstone, etc. function updateFunFacts(dob) { const month=dob.getMonth() + 1; const day=dob.getDate(); // Zodiac signs const zodiacs=[ { sign: 'Capricorn' , start: [1,1], end: [1,19] }, { sign: 'Aquarius' , start: [1,20], end: [2,18] }, { sign: 'Pisces' , start: [2,19], end: [3,20] }, { sign: 'Aries' , start: [3,21], end: [4,19] }, { sign: 'Taurus' , start: [4,20], end: [5,20] }, { sign: 'Gemini' , start: [5,21], end: [6,20] }, { sign: 'Cancer' , start: [6,21], end: [7,22] }, { sign: 'Leo' , start: [7,23], end: [8,22] }, { sign: 'Virgo' , start: [8,23], end: [9,22] }, { sign: 'Libra' , start: [9,23], end: [10,22] }, { sign: 'Scorpio' , start: [10,23], end: [11,21] }, { sign: 'Sagittarius' , start: [11,22], end: [12,21] }, { sign: 'Capricorn' , start: [12,22], end: [12,31] } ]; let zodiac='Capricorn' ; for (let z of zodiacs) { if (month===z.start[0] && day>= z.start[1] || month === z.end[0] && day <= z.end[1]) { if (z.start[0]===1 && z.start[1]===1 && month===12) continue; // avoid capricorn double zodiac=z.sign; break; } } zodiacSign.textContent=zodiac; // Birthstones const stones={ 1: 'Garnet' , 2: 'Amethyst' , 3: 'Aquamarine' , 4: 'Diamond' , 5: 'Emerald' , 6: 'Pearl' , 7: 'Ruby' , 8: 'Peridot' , 9: 'Sapphire' , 10: 'Opal' , 11: 'Topaz' , 12: 'Turquoise' }; birthstone.textContent=stones[month] || 'Unknown' ; // Birth flowers const flowers={ 1: 'Carnation' , 2: 'Violet' , 3: 'Daffodil' , 4: 'Daisy' , 5: 'Lily' , 6: 'Rose' , 7: 'Larkspur' , 8: 'Gladiolus' , 9: 'Aster' , 10: 'Marigold' , 11: 'Chrysanthemum' , 12: 'Poinsettia' }; birthFlower.textContent=flowers[month] || 'Unknown' ; // Day of week born const days=['Sunday', 'Monday' , 'Tuesday' , 'Wednesday' , 'Thursday' , 'Friday' , 'Saturday' ]; birthDayOfWeek.textContent=days[dob.getDay()]; } // Update birthday and milestones function updateBirthdayInfo(dob, today) { const birthMonth=dob.getMonth(); const birthDay=dob.getDate(); // Next birthday let nextBirthday=new Date(today.getFullYear(), birthMonth, birthDay); if (nextBirthday < today) { nextBirthday=new Date(today.getFullYear() + 1, birthMonth, birthDay); } // Format next birthday const options={ year: 'numeric' , month: 'long' , day: 'numeric' }; nextBirthdayDate.textContent=nextBirthday.toLocaleDateString(undefined, options); // Days until next birthday const diffTime=nextBirthday - today; const diffDays=Math.ceil(diffTime / (1000 * 60 * 60 * 24)); birthdayCountdown.textContent=`in ${diffDays} day${diffDays !==1 ? 's' : '' }`; // Calculate age at next birthday let nextAge=nextBirthday.getFullYear() - dob.getFullYear(); if (nextBirthday < new Date(dob.getFullYear() + nextAge, dob.getMonth(), dob.getDate())) { nextAge--; } // Milestones (upcoming 5-year marks) const currentAge=today.getFullYear() - dob.getFullYear(); const milestones=[]; for (let i=5; i <=100; i +=5) { if (i> currentAge && i <= currentAge + 25) { milestones.push(i); } } let milestoneHtml='' ; milestones.forEach(m=> { const milestoneDate = new Date(dob.getFullYear() + m, dob.getMonth(), dob.getDate()); const yearsFromNow = m - currentAge; milestoneHtml += `${m} years (in ${yearsFromNow} year${yearsFromNow !== 1 ? 's' : ''})`; }); if (milestoneHtml === '') { milestoneHtml = 'No upcoming 5-year milestones'; } milestoneList.innerHTML = milestoneHtml; } // Approximate life stats function updateLifeStats(years, days) { // Heartbeats (approx 70 bpm) const heartbeats = Math.round(days * 24 * 60 * 70); heartbeatCount.textContent = '~' + (heartbeats / 1e6).toFixed(1) + 'M'; // Earth orbits earthOrbits.textContent = years; // Sleep hours (assuming 8 hours/day) const sleepHrs = days * 8; sleepHours.textContent = '~' + (sleepHrs / 1000).toFixed(1) + 'k'; } // Event listeners calculateBtn.addEventListener('click', calculateAge); todayBtn.addEventListener('click', () => { setTodayAsOf(); calculateAge(); }); swapBtn.addEventListener('click', () => { const dob = dobInput.value; const asOf = asOfDateInput.value; if (dob && asOf) { dobInput.value = asOf; asOfDateInput.value = dob; calculateAge(); } }); presetBtns.forEach(btn => { btn.addEventListener('click', () => { const preset = btn.getAttribute('data-preset'); if (preset) { dobInput.value = preset; calculateAge(); } }); }); // Auto-calculate on page load window.addEventListener('load', calculateAge); // Also calculate when inputs change (optional) dobInput.addEventListener('change', calculateAge); asOfDateInput.addEventListener('change', calculateAge); })();