1. Chuẩn bị thư viện solarLunar
solarLunar là thư viện JavaScript cung cấp hàm chuyển đổi giữa lịch dương và lịch âm Trung Hoa. Để dùng cho lịch âm Việt Nam cơ bản (hiển thị ngày, tháng, năm âm), thư viện này là đủ cho phần lõi tính toán.
Nhúng thư viện từ CDN:
<script src="https://unpkg.com/[email protected]/lib/solarlunar.min.js"></script>
2. Cấu trúc HTML tối giản cho lịch
Trước tiên cần một khung để hiển thị lịch. Ví dụ đơn giản theo dạng lịch tháng:
<div class="calendar-nav">
<button id="prevMonth">Tháng trước</button>
<span id="calendarTitle"></span>
<button id="nextMonth">Tháng sau</button>
</div>
<div class="calendar-weekdays">
<div>CN</div>
<div>T2</div>
<div>T3</div>
<div>T4</div>
<div>T5</div>
<div>T6</div>
<div>T7</div>
</div>
<div id="calendarGrid" class="calendar-grid"></div>
Lưới calendarGrid sẽ được JavaScript render từng ô ngày, mỗi ô gồm ngày dương và ngày âm.
3. Hàm chuyển đổi ngày dương sang ngày âm với solarLunar
solarLunarcung cấp hàm solar2lunar(year, month, day). Tháng được tính từ 1 đến 12, khác với JavaScript Date dùng 0 đến 11. Kết quả trả về là một object chứa thông tin năm, tháng, ngày âm cùng nhiều dữ liệu khác.
Ví dụ chuyển đổi một ngày cụ thể:
function chuyenDoiNgayDuongSangAm(year, month, day) {
if (!window.solarlunar || !solarlunar.solar2lunar) {
console.error("Thiếu thư viện solarlunar");
return null;
}
// month: 1-12
var lunar = solarlunar.solar2lunar(year, month, day);
// lunar.lYear, lunar.lMonth, lunar.lDay
console.log("Âm lịch:", lunar.lDay + "/" + lunar.lMonth + "/" + lunar.lYear);
return lunar;
}
Từ hàm này, bạn có thể dùng lại trong logic render lịch để hiển thị ngày âm cho từng ô.
4. Render lịch tháng và gắn ngày âm
Bước tiếp theo là viết hàm tạo lịch tháng. Ý tưởng: tính ngày đầu tháng rơi vào thứ mấy, số ngày trong tháng, sau đó lặp 42 ô (6 hàng x 7 cột). Với mỗi ngày hợp lệ, gọi solar2lunar để lấy ngày âm.
var today = new Date();
var currentMonth = today.getMonth(); // 0-11
var currentYear = today.getFullYear(); // ví dụ 2025
function renderCalendar(monthIndex, year) {
var grid = document.getElementById("calendarGrid");
var title = document.getElementById("calendarTitle");
grid.innerHTML = "";
title.textContent = "Tháng " + (monthIndex + 1) + " / " + year;
var firstDay = new Date(year, monthIndex, 1).getDay(); // 0 = CN
var daysInMonth = new Date(year, monthIndex + 1, 0).getDate();
for (var i = 0; i < 42; i++) {
var cell = document.createElement("div");
cell.className = "calendar-cell";
var dayNumber = i - firstDay + 1;
if (dayNumber < 1 || dayNumber > daysInMonth) {
cell.classList.add("calendar-empty");
grid.appendChild(cell);
continue;
}
// Tính âm lịch
var lunar = solarlunar.solar2lunar(
year,
monthIndex + 1,
dayNumber
);
var solarHtml = '<div class="day-solar">' + dayNumber + '</div>';
var lunarHtml = '<div class="day-lunar">' + lunar.lDay + '</div>';
cell.innerHTML = solarHtml + lunarHtml;
grid.appendChild(cell);
}
}
// Khởi tạo lần đầu
renderCalendar(currentMonth, currentYear);
Đoạn mã trên đã đủ để tạo một lịch tháng có hiển thị số âm ở góc dưới mỗi ô ngày.
5. Thêm nút chuyển tháng trước và tháng sau
Để lịch sử dụng thực tế, bạn nên thêm xử lý cho hai nút chuyển tháng. Logic rất đơn giản: thay đổi currentMonth và currentYear, sau đó gọi lại renderCalendar.
document.getElementById("prevMonth").addEventListener("click", function () {
currentMonth--;
if (currentMonth < 0) {
currentMonth = 11;
currentYear--;
}
renderCalendar(currentMonth, currentYear);
});
document.getElementById("nextMonth").addEventListener("click", function () {
currentMonth++;
if (currentMonth > 11) {
currentMonth = 0;
currentYear++;
}
renderCalendar(currentMonth, currentYear);
});
Ngoài ra, bạn cũng có thể xử lý phím Enter hoặc input chọn tháng, năm để nhảy đến bất kỳ tháng nào mà vẫn tái sử dụng cùng một hàm render.
6. Gợi ý CSS cơ bản cho lịch âm
Để lịch dễ nhìn hơn, bạn nên dùng grid 7 cột và style riêng cho ngày dương, ngày âm, ô trống.
.calendar-weekdays,
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, minmax(0, 1fr));
}
.calendar-weekdays > div {
text-align: center;
padding: 6px 0;
font-weight: 600;
font-size: 13px;
}
.calendar-grid {
border-top: 1px solid #eee;
border-left: 1px solid #eee;
}
.calendar-cell {
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
padding: 6px 8px 10px;
min-height: 70px;
box-sizing: border-box;
}
.calendar-empty {
background: #fafafa;
}
.day-solar {
font-size: 15px;
font-weight: 600;
}
.day-lunar {
font-size: 12px;
color: #888;
margin-top: 2px;
}
Với đoạn CSS này, lịch âm sẽ hiển thị dưới dạng 7 cột, ngày dương nổi bật, ngày âm nhỏ hơn ở bên dưới nhưng vẫn dễ đọc.
7. Mở rộng: sự kiện, click chi tiết, hỗ trợ mobile
Sau khi đã có lịch âm cơ bản, bạn có thể tiếp tục nâng cấp:
- Gán sự kiện cho từng ngày (ví dụ Tết, Giáng Sinh) bằng cách định nghĩa mảng cấu hình rồi so khớp trong vòng lặp.
- Thêm sự kiện click vào ô ngày để mở popup hiển thị đầy đủ ngày âm, ngày dương và mô tả sự kiện.
- Hỗ trợ vuốt trái, vuốt phải trên mobile để chuyển tháng, giúp trải nghiệm giống ứng dụng native.
- Kết hợp với localStorage để lưu tháng cuối cùng người dùng xem và tải lại đúng trạng thái đó.
8. Kết luận
Xây dựng một lịch âm với JavaScript không hề khó nếu bạn tách rõ hai phần: phần tính toán do thư viện solarLunar đảm nhiệm và phần hiển thị do bạn điều khiển bằng DOM và CSS. Chỉ với một vài hàm quan trọng như solar2lunar, vòng lặp sinh ô lịch và xử lý nút chuyển tháng, bạn đã có thể tạo ra một lịch âm dương đầy đủ cho website, sau đó phát triển thêm các tính năng nâng cao theo nhu cầu riêng.
Hokage69th
05/12/2025 lúc 10:50
có thể cho mình source cái lịch này không?
Admin
05/12/2025 lúc 11:00
đã có link tải rồi đó bạn