一枚日历的成长史

时间:2015-10-15 作者:剧中人

WEB开发中,常常会涉及到对日期的选择操作,日历控件的使用尤为频繁,今天小剧就来扒一扒如何一步步实现一枚日历。

在说实现之前,先来看一看WEB中常见的日历形态。

1、携程酒店预订

携程酒店预订

2、新浪微博定时发送

新浪微博定时发送

3、途牛旅游线路预订

途牛旅游线路预订

1、携程、新浪的例子可以叫做选择类的日历,算是日历中最常见的形态了。设置个人生日的时候、12306选择车票出行时间、预订酒店等场景下都会用得到。这类日历相对简单,使用时弹出,不用时隐藏,既不占用页面空间又能简单快捷的完成日期选择的功能。

2、途牛这个例子展示信息比较丰满,相对来说更个性化一点儿。这类日历更偏向于展示行程安排、重要时间点及节假日标记等。将日历作为一个容器直观的呈现日期上的内容,便于规划日程安排。

准备工作开始啦

啰嗦了这些,再来回到日历自身。一个日历精简之后骨架是什么呢,实现一枚日历所需要完成的最小部分是什么?

很显然,是渲染一个完整的月份,即按星期显示一个月的每一天。

开工,现在就来动手实现单个月份的渲染。这里有几个关键点需要解决,先一一列出来:

好啦,现在其实就只有两点需要解决。

如何获取某月第一天是星期几?

其实这个相对来说比较简单,只要将日期设置为对应年、月份、日期为第一天即可。

function getFirstDayInMonth(year,month){
   //创建一个Date对象
   var date = new Date();
   //设置年份为输入年份
   date.setFullYear(year);
   //设置月份(输入月份为自然月,即一月为1,Date中的月份是以0开始)
   date.setMonth(month-1);
   //设置日期
   date.setDate(1);
   //返回Date对象是周几
   return date.getDay();
}

当然,上面步骤过于繁琐,简单点儿即可改为下面。

function getFirstDayInMonth(year,month){
    return new Date(year,month-1,1).getDay();
}

好了,现在只要告诉我年、月,我就可以马上告诉你这个月第一天是星期几啦。

怎样获取某月日期的长度?

这一步更简单,只要设置好年份,将日期设置为下个月第一天,然后再减去一天,即可回到当前月份的最后一天,然后再获取date即可得到当前月份日期的长度。

function getDateLengthInMonth(year,month){
    //创建一个Date对象
    var date = new Date();
    //设置年份为输入年份
    date.setFullYear(year);
    //设置月份(减一再加一是不是很蛋疼)
    date.setMonth(month -1 + 1);
    //设置日期
    date.setDate(1);
    //将时间减去一天(仔细想想1000是个什么鬼)
    date.setTime(date.getTime() - 1000 * 60*60*24)
    //返回Date对象是日期是多少
    return  date.getDate();
}

又是一段又臭又长代码,好恶心哦!当然有个取巧的方式,设置为下个月日期为零,也可以达到上面同等效果,看看下面这段是不是清爽多了。

function getDateLengthInMonth(year,month){
    return new Date(year,month,0).getDate();
}

然后捏,日历在哪儿?

好嘞,日历登场了,为了说明方便,这里不使用任何模板引擎,直接用拼接字符串的方式来生成一个日历的html。

function PaintMonthTable(year,month){
        //获取当前月第一天是周几
    var firstDay = getFirstDayInMonth(year,month),
        //获取当前月日期长度
        length = getDateLengthInMonth(year,month),
        i,
        html = '<div class="calender-month">';

    //构建星期
    html += '<div class="calender-caption">';
    for(i=0;i<7;i++){
        html += '<div class="calender-cell">' + private_Day_title[i] + '</div>';
    }
    html += '</div>';

    //构建日期列表
    html += '<div class="calender-content">';
    //循环输出月前空格
    for(i=1;i<firstDay+1;i++){
        html += '<div class="calender-cell"></div>';
    }
    //循环输出当前月所有天
    for(i=1;i<length+1;i++){
        html += '<div class="calender-cell">' + i + '</div>';
    }
    html += '</div>';

    return html;
}

这就结束了?

对的,今天小剧要分享的到这儿就结束了。

上面仅仅是一个生成对应年、月的单月HTML而已,不包含首尾上下个月补全(Demo2里有实现),不包含一个星期的第一天是星期几的配置,代码粗犷没有任何包装。只能做为参考。

不过明白了生成日历的基本过程后,在此基础之上,实现一个较为复杂的日历还是比较容易的。

下面是demo链接和截图,希望对你有所帮助,但愿下次再有日历的需求时,你的第一反应不再是满世界找插件了。

这是一个Demo