<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>春节倒计时</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#E63946',
secondary: '#FFB703',
dark: '#1D3557',
light: '#F1FAEE',
festival: '#FF5722', // 新增节日颜色
solar: '#2196F3', // 新增节气颜色
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.text-shadow {
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.animate-float {
animation: float 3s ease-in-out infinite;
}
.animate-pulse-slow {
animation: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.text-festival {
color: #FF5722;
}
.text-solar {
color: #2196F3;
}
}
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
</style>
</head>
<body class="bg-gradient-to-br from-light to-blue-50 min-h-screen flex flex-col items-center justify-center p-4 font-sans">
<div class="w-full max-w-3xl bg-white rounded-2xl shadow-xl overflow-hidden transform transition-all duration-500 hover:shadow-2xl">
<!-- 顶部装饰条 -->
<div class="h-2 bg-gradient-to-r from-primary to-secondary"></div>
<!-- 主要内容区 -->
<div class="p-6 md:p-10 text-center">
<h1 class="text-[clamp(1.8rem,5vw,2.5rem)] font-bold text-dark mb-4">春节倒计时</h1>
<p class="text-gray-600 mb-8 text-[clamp(1rem,2vw,1.2rem)]">距离农历新年还有</p>
<!-- 倒计时显示 -->
<div class="mb-8">
<div id="countdown" class="text-[clamp(3rem,15vw,8rem)] font-black text-primary mb-2 leading-tight text-shadow animate-pulse-slow">
<span id="days">0</span>
</div>
<div class="text-[clamp(1.5rem,3vw,2rem)] font-bold text-dark mb-6">天</div>
</div>
<!-- 当前日期(包含农历、星期、时钟、节气和节日) -->
<div id="current-date" class="text-gray-500 mb-4 text-[clamp(1rem,2vw,1.2rem)]"></div>
<!-- 节气和节日信息 -->
<div id="solar-festival" class="text-gray-700 mb-8 text-[clamp(1rem,2vw,1.2rem)]"></div>
<!-- 春节信息 -->
<div class="bg-light rounded-xl p-4 mb-6">
<p class="text-gray-700 mb-2">下一个春节是:<span id="next-cny-date" class="font-medium text-dark"></span></p>
<p class="text-gray-700">农历<span id="next-cny-year" class="font-medium text-dark"></span>年正月初一</p>
</div>
<!-- 装饰元素 -->
<div class="flex justify-center space-x-4 mt-8">
<i class="fa-solid fa-firecracker text-secondary text-2xl animate-float" style="animation-delay: 0s"></i>
<i class="fa-solid fa-gift text-secondary text-2xl animate-float" style="animation-delay: 0.5s"></i>
<i class="fa-solid fa-calendar-check text-secondary text-2xl animate-float" style="animation-delay: 1s"></i>
</div>
</div>
<!-- 底部 -->
<div class="bg-dark text-white p-4 text-center text-sm">
<p>愿新年,胜旧年 <i class="fa-solid fa-heart text-primary ml-1"></i></p>
</div>
</div>
<script>
// 农历月份名称
const lunarMonths = ['正', '二', '三', '四', '五', '六', '七', '八', '九', '十', '冬', '腊'];
// 农历日期名称
const lunarDays = ['初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十',
'十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十',
'廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十'];
// 星期名称
const weekDays = ['日', '一', '二', '三', '四', '五', '六'];
// 24节气名称
const solarTerms = [
'立春', '雨水', '惊蛰', '春分', '清明', '谷雨',
'立夏', '小满', '芒种', '夏至', '小暑', '大暑',
'立秋', '处暑', '白露', '秋分', '寒露', '霜降',
'立冬', '小雪', '大雪', '冬至', '小寒', '大寒'
];
// 2024-2025年节气数据(公历日期)
const solarTermData = {
2024: [
[2, 4], [2, 19], [3, 5], [3, 20], [4, 4], [4, 20],
[5, 5], [5, 21], [6, 6], [6, 21], [7, 7], [7, 23],
[8, 7], [8, 23], [9, 8], [9, 23], [10, 8], [10, 24],
[11, 7], [11, 22], [12, 7], [12, 22], [1, 6], [1, 20]
],
2025: [
[2, 3], [2, 18], [3, 5], [3, 20], [4, 4], [4, 19],
[5, 5], [5, 21], [6, 5], [6, 21], [7, 6], [7, 22],
[8, 7], [8, 23], [9, 7], [9, 23], [10, 8], [10, 23],
[11, 7], [11, 22], [12, 7], [12, 21], [1, 5], [1, 20]
]
};
// 中国传统节日数据(农历日期)
const festivals = {
'1-1': { name: '春节', importance: 1 },
'1-15': { name: '元宵节', importance: 2 },
'5-5': { name: '端午节', importance: 2 },
'7-7': { name: '七夕节', importance: 3 },
'8-15': { name: '中秋节', importance: 1 },
'9-9': { name: '重阳节', importance: 2 },
'12-8': { name: '腊八节', importance: 3 },
'12-23': { name: '小年', importance: 3 }
};
// 农历数据(简化版,仅包含2024-2025年部分数据)
const lunarData = {
2024: {
startMonth: 2, // 春节所在公历月份 (2月)
startDay: 10, // 春节所在公历日期 (10日)
months: [30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30] // 各农历月天数
},
2025: {
startMonth: 1, // 春节所在公历月份 (1月)
startDay: 29, // 春节所在公历日期 (29日)
months: [29, 30, 29, 30, 29, 30, 29, 30, 30, 29, 30, 29] // 各农历月天数
}
};
// 计算春节日期的函数
function calculateChineseNewYear(currentYear) {
// 这里使用简化的算法,实际春节日期需要更复杂的农历计算
// 以下数据是2024-2030年的春节日期,实际应用中可能需要更完善的农历算法
const springFestivalDates = {
2024: new Date(2024, 1, 10), // 2024年2月10日
2025: new Date(2025, 0, 29), // 2025年1月29日
2026: new Date(2026, 1, 17), // 2026年2月17日
2027: new Date(2027, 1, 6), // 2027年2月6日
2028: new Date(2028, 1, 25), // 2028年2月25日
2029: new Date(2029, 1, 13), // 2029年2月13日
2030: new Date(2030, 2, 3) // 2030年3月3日
};
const currentDate = new Date();
const currentMonth = currentDate.getMonth();
const currentDay = currentDate.getDate();
// 确定使用哪一年的春节日期
let targetYear = currentYear;
if (currentMonth > 1 || (currentMonth === 1 && currentDay > 20)) {
targetYear = currentYear + 1;
}
// 如果不在预定义范围内,使用一个估计值(实际应用中需要更完善的算法)
if (!springFestivalDates[targetYear]) {
// 估计值:假设春节在2月1日左右
return {
date: new Date(targetYear, 1, 1),
yearName: '未知'
};
}
// 生肖年份
const zodiacYears = ['龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪', '鼠', '牛', '虎', '兔'];
const startYear = 2024; // 2024年是龙年
const offset = (targetYear - startYear) % 12;
const zodiacIndex = offset >= 0 ? offset : offset + 12;
const yearName = zodiacYears[zodiacIndex];
return {
date: springFestivalDates[targetYear],
yearName: yearName
};
}
// 计算农历日期(简化版,仅适用于2024-2025年)
function calculateLunarDate(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1; // 公历月份 (1-12)
const day = date.getDate(); // 公历日期
// 仅处理2024-2025年的数据
if (!lunarData[year]) {
return {
lunarDate: "未知",
lunarMonth: 0,
lunarDay: 0
};
}
const lunarInfo = lunarData[year];
const springFestival = new Date(year, lunarInfo.startMonth - 1, lunarInfo.startDay);
const daysFromSpringFestival = Math.floor((date - springFestival) / (1000 * 60 * 60 * 24));
// 如果日期在春节之前,计算上一年的农历日期
if (daysFromSpringFestival < 0) {
const prevYear = year - 1;
if (!lunarData[prevYear]) {
return {
lunarDate: "未知",
lunarMonth: 0,
lunarDay: 0
};
}
const prevYearInfo = lunarData[prevYear];
const prevYearSpringFestival = new Date(prevYear, prevYearInfo.startMonth - 1, prevYearInfo.startDay);
const daysFromPrevSpringFestival = Math.floor((date - prevYearSpringFestival) / (1000 * 60 * 60 * 24));
let lunarMonth = 0;
let lunarDay = 0;
let daysLeft = daysFromPrevSpringFestival;
// 计算农历月份和日期
for (let i = 0; i < 12; i++) {
if (daysLeft < prevYearInfo.months[i]) {
lunarMonth = i + 1;
lunarDay = daysLeft + 1;
break;
}
daysLeft -= prevYearInfo.months[i];
}
return {
lunarDate: `农历${lunarMonths[lunarMonth - 1]}月${lunarDays[lunarDay - 1]}`,
lunarMonth: lunarMonth,
lunarDay: lunarDay
};
}
// 如果日期在春节之后
else {
let lunarMonth = 0;
let lunarDay = 0;
let daysLeft = daysFromSpringFestival;
// 计算农历月份和日期
for (let i = 0; i < 12; i++) {
if (daysLeft < lunarInfo.months[i]) {
lunarMonth = i + 1;
lunarDay = daysLeft + 1;
break;
}
daysLeft -= lunarInfo.months[i];
}
return {
lunarDate: `农历${lunarMonths[lunarMonth - 1]}月${lunarDays[lunarDay - 1]}`,
lunarMonth: lunarMonth,
lunarDay: lunarDay
};
}
}
// 检查是否为节气
function checkSolarTerm(date) {
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
if (!solarTermData[year]) return null;
for (let i = 0; i < solarTermData[year].length; i++) {
const [termMonth, termDay] = solarTermData[year][i];
if (month === termMonth && day === termDay) {
return solarTerms[i];
}
}
return null;
}
// 检查是否为节日
function checkFestival(lunarMonth, lunarDay) {
const key = `${lunarMonth}-${lunarDay}`;
return festivals[key] || null;
}
// 更新倒计时
function updateCountdown() {
const now = new Date();
const currentYear = now.getFullYear();
// 获取下一个春节的日期
const nextCny = calculateChineseNewYear(currentYear);
// 计算剩余天数
const timeDiff = nextCny.date - now;
const daysLeft = Math.ceil(timeDiff / (1000 * 60 * 60 * 24));
// 计算农历日期
const lunarInfo = calculateLunarDate(now);
// 获取星期和时间
const weekDay = `星期${weekDays[now.getDay()]}`;
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const timeStr = `${hours}:${minutes}:${seconds}`;
// 检查是否为节气
const solarTerm = checkSolarTerm(now);
// 检查是否为节日
const festival = checkFestival(lunarInfo.lunarMonth, lunarInfo.lunarDay);
// 更新DOM
document.getElementById('days').textContent = daysLeft;
document.getElementById('current-date').textContent =
`今天是 ${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日 ${weekDay} · ${lunarInfo.lunarDate} ${timeStr}`;
document.getElementById('next-cny-date').textContent =
`${nextCny.date.getFullYear()}年${nextCny.date.getMonth() + 1}月${nextCny.date.getDate()}日`;
document.getElementById('next-cny-year').textContent = nextCny.yearName;
// 更新节气和节日信息
let solarFestivalHTML = '';
if (solarTerm) {
solarFestivalHTML += `<span class="text-solar"><i class="fa-solid fa-sun mr-1"></i>${solarTerm}</span>`;
}
if (festival) {
if (solarFestivalHTML) solarFestivalHTML += ' · ';
const importanceClass = festival.importance === 1 ? 'font-bold' : '';
solarFestivalHTML += `<span class="text-festival ${importanceClass}"><i class="fa-solid fa-calendar-check mr-1"></i>${festival.name}</span>`;
}
document.getElementById('solar-festival').innerHTML = solarFestivalHTML;
}
// 初始化
updateCountdown();
// 每秒更新时间
setInterval(updateCountdown, 1000);
</script>
</body>
</html>