<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Age Calculator</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Custom styles for professional look and feel */
body {
font-family: 'Inter', sans-serif;
background-color: #f0f4f8; /* Light blue-gray background */
}
.shadow-custom {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.05), 0 6px 6px rgba(0, 0, 0, 0.05);
}
.primary-color {
color: #1e40af; /* Darker blue for primary text */
}
.secondary-bg {
background-color: #f7f9fb; /* Light background for detail section */
}
</style>
</head>
<body class="min-h-screen flex items-start justify-center p-4 sm:p-8">
<div class="w-full max-w-4xl bg-white rounded-xl shadow-custom overflow-hidden mt-8">
<!-- Header -->
<div class="bg-gray-800 text-white p-4 text-center text-xl font-bold rounded-t-xl">
Date of Birth & Age Calculator
</div>
<div class="p-6 md:p-8">
<h1 class="text-3xl font-extrabold primary-color mb-6 border-b pb-2">Calculate Your Age</h1>
<form id="age-calculator-form" class="space-y-6">
<!-- Date Inputs -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-2">
<label for="dob-input" class="block text-sm font-medium text-gray-700">Date of Birth</label>
<input type="date" id="dob-input" required class="w-full p-3 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition duration-150">
</div>
<div class="space-y-2">
<label for="target-date-input" class="block text-sm font-medium text-gray-700">Age at the Date of</label>
<input type="date" id="target-date-input" required class="w-full p-3 border border-gray-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition duration-150">
</div>
</div>
<!-- Buttons -->
<div class="flex flex-col sm:flex-row gap-4 pt-4">
<button type="submit" class="w-full sm:w-auto px-6 py-3 bg-blue-600 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 transition duration-150 transform hover:scale-[1.02]">
Calculate Age
</button>
<button type="button" id="reset-btn" class="w-full sm:w-auto px-6 py-3 bg-gray-200 text-gray-800 font-semibold rounded-lg shadow-md hover:bg-gray-300 transition duration-150">
Reset
</button>
</div>
</form>
<!-- Results Section -->
<div id="results-container" class="mt-10 hidden">
<div id="error-message" class="hidden p-3 bg-red-100 border border-red-400 text-red-700 rounded-lg mb-6 font-medium"></div>
<!-- Primary Age Result (Years, Months, Days) -->
<div class="mb-8 p-4 bg-yellow-50 rounded-lg border border-yellow-200">
<h2 class="text-2xl font-bold primary-color mb-3 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2 text-yellow-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
Your Age
</h2>
<p id="age-summary" class="text-3xl sm:text-4xl font-extrabold text-gray-800"></p>
</div>
<!-- Next Birthday Countdown -->
<div class="mb-8 p-4 bg-green-50 rounded-lg border border-green-200">
<h2 class="text-2xl font-bold text-green-700 mb-3 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" /></svg>
Next Birthday
</h2>
<p id="next-birthday-date" class="text-lg font-semibold text-gray-700 mb-2"></p>
<p id="next-birthday-countdown" class="text-xl font-bold text-green-600"></p>
</div>
<!-- Age in Total Units Breakdown -->
<h2 class="text-2xl font-bold primary-color mb-4 mt-8">Age in Total Time Units</h2>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-4 secondary-bg p-4 rounded-lg">
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-months" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Months</span></div>
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-weeks" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Weeks</span></div>
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-days" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Days</span></div>
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-hours" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Hours</span></div>
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-minutes" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Minutes</span></div>
<div class="p-3 bg-white rounded-lg border border-gray-200"><span id="total-seconds" class="block text-2xl font-bold text-indigo-600">0</span> <span class="text-sm text-gray-500">Seconds</span></div>
</div>
</div>
</div>
</div>
<!-- JavaScript Logic -->
<script>
document.addEventListener('DOMContentLoaded', () => {
const dobInput = document.getElementById('dob-input');
const targetDateInput = document.getElementById('target-date-input');
const form = document.getElementById('age-calculator-form');
const resetBtn = document.getElementById('reset-btn');
const resultsContainer = document.getElementById('results-container');
const errorMessageDiv = document.getElementById('error-message');
// Helper function to pad numbers
const pad = (num) => num < 10 ? '0' + num : num;
// Set default target date to today
const today = new Date();
const todayStr = `${today.getFullYear()}-${pad(today.getMonth() + 1)}-${pad(today.getDate())}`;
targetDateInput.value = todayStr;
/**
* Calculates the difference between two dates in Years, Months, and Days.
* Logic adapted for common age calculator requirements (e.g., Feb 28 to Mar 28 is 1 month).
* @param {Date} date1 - Start Date (DOB)
* @param {Date} date2 - End Date (Target Date)
* @returns {{years: number, months: number, days: number}}
*/
function calculateAgeYMD(date1, date2) {
let y1 = date1.getFullYear(), m1 = date1.getMonth(), d1 = date1.getDate();
let y2 = date2.getFullYear(), m2 = date2.getMonth(), d2 = date2.getDate();
let years = y2 - y1;
let months = m2 - m1;
let days = d2 - d1;
if (days < 0) {
// Borrow from the month
months--;
// Get the number of days in the previous month (month before d2)
let daysInPrevMonth = new Date(y2, m2, 0).getDate();
days += daysInPrevMonth;
}
if (months < 0) {
// Borrow from the year
years--;
months += 12;
}
return { years, months, days };
}
/**
* Calculates the next birthday and time remaining.
* @param {Date} dob - Date of Birth
* @param {Date} targetDate - The date to calculate the countdown from
* @returns {{nextBirthdayDate: Date, remainingTimeMs: number}}
*/
function getNextBirthday(dob, targetDate) {
let nextBirthday = new Date(dob);
nextBirthday.setFullYear(targetDate.getFullYear());
// If the birthday has already passed this year, set it for next year
if (nextBirthday < targetDate) {
nextBirthday.setFullYear(targetDate.getFullYear() + 1);
}
const remainingTimeMs = nextBirthday.getTime() - targetDate.getTime();
return { nextBirthdayDate: nextBirthday, remainingTimeMs };
}
/**
* Calculates total time units (months, days, hours, etc.)
* @param {Date} date1 - Start Date (DOB)
* @param {Date} date2 - End Date (Target Date)
* @returns {{totalMs: number, totalMonths: number}}
*/
function calculateTotalUnits(date1, date2) {
const totalMs = date2.getTime() - date1.getTime();
// Calculate total months using YMD difference
const { years, months } = calculateAgeYMD(date1, date2);
const totalMonths = (years * 12) + months;
return { totalMs, totalMonths };
}
// --- Core Calculation & Display Function ---
function displayResults(dob, targetDate) {
const birthDate = new Date(dob);
const target = new Date(targetDate);
// --- 1. Validate Dates ---
if (birthDate > target) {
errorMessageDiv.textContent = "Error: Date of Birth cannot be after the 'Age at the Date of' date. Please correct the dates.";
errorMessageDiv.classList.remove('hidden');
resultsContainer.classList.add('hidden');
return;
} else {
errorMessageDiv.classList.add('hidden');
}
// --- 2. Calculate Age in YMD ---
const { years, months, days } = calculateAgeYMD(birthDate, target);
document.getElementById('age-summary').innerHTML =
`<span class="text-blue-700">${years}</span> Years, <span class="text-blue-700">${months}</span> Months, and <span class="text-blue-700">${days}</span> Days.`;
// --- 3. Calculate Total Time Units ---
const { totalMs, totalMonths } = calculateTotalUnits(birthDate, target);
const totalDays = Math.floor(totalMs / (1000 * 60 * 60 * 24));
const totalWeeks = Math.floor(totalDays / 7);
const totalHours = Math.floor(totalMs / (1000 * 60 * 60));
const totalMinutes = Math.floor(totalMs / (1000 * 60));
const totalSeconds = Math.floor(totalMs / 1000);
document.getElementById('total-months').textContent = totalMonths.toLocaleString();
document.getElementById('total-weeks').textContent = totalWeeks.toLocaleString();
document.getElementById('total-days').textContent = totalDays.toLocaleString();
document.getElementById('total-hours').textContent = totalHours.toLocaleString();
document.getElementById('total-minutes').textContent = totalMinutes.toLocaleString();
document.getElementById('total-seconds').textContent = totalSeconds.toLocaleString();
// --- 4. Calculate Next Birthday ---
const { nextBirthdayDate, remainingTimeMs } = getNextBirthday(birthDate, target);
const nextBirthdayFormatted = nextBirthdayDate.toLocaleDateString('en-US', {
weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
});
const remainingDays = Math.ceil(remainingTimeMs / (1000 * 60 * 60 * 24));
const remainingHours = Math.floor((remainingTimeMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const remainingMinutes = Math.floor((remainingTimeMs % (1000 * 60 * 60)) / (1000 * 60));
const remainingSeconds = Math.floor((remainingTimeMs % (1000 * 60)) / 1000);
document.getElementById('next-birthday-date').textContent =
`Your next birthday is on: ${nextBirthdayFormatted}`;
document.getElementById('next-birthday-countdown').textContent =
`${remainingDays.toLocaleString()} Days`;
// Optionally display full countdown (Days, Hours, Minutes, Seconds)
// document.getElementById('next-birthday-countdown').textContent =
// `${remainingDays} days, ${remainingHours} hours, ${remainingMinutes} minutes, ${remainingSeconds} seconds`;
resultsContainer.classList.remove('hidden');
}
// --- Event Listeners ---
form.addEventListener('submit', function(event) {
event.preventDefault();
displayResults(dobInput.value, targetDateInput.value);
});
resetBtn.addEventListener('click', () => {
form.reset();
targetDateInput.value = todayStr; // Reset target date to today
resultsContainer.classList.add('hidden');
errorMessageDiv.classList.add('hidden');
});
});
</script>
</body>
</html>
Comments
Post a Comment