JavaScript 实现简易日历算法详解

作者:流萤

时间:2026-10-21

浏览:96

本文介绍使用JavaScript实现简易日历的算法逻辑。核心步骤包括通过自定义函数判断闰年以确定二月天数,利用Date对象获取当月第一天星期数,计算表格所需行数,并通过嵌套循环渲染日期单元格。同时涵盖跨月逻辑处理及DOM更新机制,适合前端开发参考。

文章目录

JavaScript 实现简易日历算法详解

近期开发中遇到了需要支持文本编辑功能的日历组件需求。为了便于数据绑定,决定使用JavaScript编写一套日历逻辑。其核心思想相对直观。

具体实现流程如下:

获取当月总天数与闰年判断

第一步,获取当前处理月份的总天数。

JavaScript标准库未直接提供此参数,需自行计算。由于闰年会影响二月天数,首先编写一个判断闰年的辅助函数:


function is_leap(year) {
 return (year%100==0?res=(year%400==0?1:0):res=(year%4==0?1:0));
}

第二步,定义一个包含十二个月份总天数的数组:


m_days=new Array(31,28+is_leap(ynow),31,30,31,31,30,31,30,31,30,31);

在该数组中,二月天数已结合闰年判断结果(28 + is_leap(ynow))。数组索引从0开始,恰好对应JavaScript Date对象getMonth方法的返回值(0代表一月,1代表二月,依此类推)。

由此,各月总天数可通过m_days[x]获取,其中x为0至11的整数。

计算首日星期数与表格行数

第三步,计算处理月份的第一天是星期几。

可以利用Date对象的getDay()方法获取,返回值范围为0至6,其中0代表星期一,1代表星期二,2代表星期三,后续依次类推。示例代码(设定处理时间为2008年3月)如下:


n1str=new Date(2008,3,1);
firstday=n1str.getDay();

已知当月总天数和首日星期数后,即可确定表格所需的行数:(当月天数 + 首日星期数值) / 7。因表格行数需为整数,使用Math.ceil函数处理:


tr_str=Math.ceil((m_days[mnow] + firstday)/7);

HTML中的tr标签代表表格行,因此变量tr_str是构建表格结构的关键依据。

日历表格渲染与跨月逻辑

第四步,生成日历表格。

通过两层for循环实现:外层循环控制行,内层循环控制单元格。


for(i=0;i<tr_str;i++) { //表格的行
  for(k=0;k<7;k++) { //表格每行的单元格
    idx=i*7+k; //单元格自然序列号
    date_str=idx-firstday+1; //计算日期
    (date_str<=0 || date_str>m_days[mnow]) ? date_str="&nbsp;" : date_str=idx-firstday+1; //过滤无效日期(小于等于零的、大于月总天数的)
    $(".date-info .date").last().append("<td class='day'>" + date_str + "</td>");
  }
}

判断单元格序号是否代表有效日期至关重要,需加入过滤机制:仅输出大于0且小于等于当月总天数的日期。

第五步,处理上一个月与下一个月逻辑。


if(mnow<=0){
  mnow=11;
  ynow=ynow-1;
}else{
  mnow--;
}

if(mnow>=11){
  mnow=0;
  ynow=ynow+1;
}else{
  mnow++;
}

获取上月时需特别注意1月的边界情况;获取下月时需关注12月的边界情况。

渲染新日历前,需先移除旧日历DOM元素,再添加新的日历结构。


var nstr = new Date();
var ynow = nstr.getFullYear();
var mnow = nstr.getMonth();
var dnow = nstr.getDate();
var mnow_real = mnow;
calendar(nstr,ynow,mnow,dnow);
monDetail(ynow,mnow_real);

function monDetail(ynow,mnow){
 mnow_real = mnow+1;
 $(".month-detail").html(ynow+"-"+ mnow_real); //显示当前年月
}

function is_leap(year) { //判断是否为闰年
 return (year%100==0?res=(year%400==0?1:0):res=(year%4==0?1:0));
}

function preMonth(){ //上一个月
 console.log(mnow);
 if(mnow<=0){
 mnow=11;
 ynow=ynow-1;
 }else{
 mnow--;
 } 
 calendar(nstr,ynow,mnow,dnow);
 monDetail(ynow,mnow);
}

function nextMonth(){ //下一个月

 if(mnow>=11){
 mnow=0;
 ynow=ynow+1;
 }else{
 mnow++;
 }
 calendar(nstr,ynow,mnow,dnow);
 monDetail(ynow,mnow);

}

function calendar(nstr,ynow,mnow,dnow){
 $(".date-info tr.date").remove(); /改变月份时,先移除旧的日期
 var nlstr = new Date(ynow,mnow,1); //当月第一天
 var firstday = nlstr.getDay(); //第一天星期几

 var m_days=new Array(31,28+is_leap(ynow),31,30,31,31,30,31,30,31,30,31); //每个月的天数

 var tr_str=Math.ceil((m_days[mnow] + firstday)/7); //当前月天数+第一天是星期几的数值 获得 表格行数
 var i,k,idx,date_str;
 for(i=0;i<tr_str;i++) { //表格的行
 $(".date-info tbody").append("<tr class='date'></tr>");
 for(k=0;k<7;k++) { //表格每行的单元格
 idx=i*7+k; //单元格自然序列号
 date_str=idx-firstday+1; //计算日期
 (date_str<=0 || date_str>m_days[mnow]) ? date_str="&nbsp;" : date_str=idx-firstday+1; //过滤无效日期(小于等于零的、大于月总天数的)
 $(".date-info .date").last().append("<td class='day'>" + date_str + "</td>");
 }
 
 }
}

以上内容为本文全部要点,希望能为读者提供学习参考,也欢迎大家支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章