alendar 是与日历相关的模块,该模块定义了很多类型,主要包括:Calendar、TextCalendar、HTMLCalendar,其中 Calendar 是 TextCalendar 和 HTMLCalendar 的基类,这些类有着十分丰富的日历处理方法。
对于简单的文本日历,我们使用 calendar 模块直接调用的方法或属性即可,下面来具体看一下。
设置每一周的开始(0 表示星期一,6 表示星期天),calendar 提供了 MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY 和 SUNDAY 几个常量方便使用。例如,设置每周的第一天为星期天,示例如下:
import calendar
calendar.setfirstweekday(calendar.SUNDAY)
返回当前设置的每星期的第一天的数值,默认为星期一。示例如下:
import calendar
print(calendar.firstweekday())
如果 year 是闰年则返回 True,否则返回 False。示例如下:
import calendar
print(calendar.isleap(9102))
返回在范围 y1 至 y2 (包含 y1 和 y2 )之间的闰年的年数,其中 y1 和 y2 是年份。示例如下:
import calendar
print(calendar.leapdays(1945,2019))
返回一周中的某一天 ( 0 ~ 6 代表周一至周日)。示例如下:
import calendar
print(calendar.weekday(2019,10,1))
返回指定年、月份第一天是星期几和这个月的天数。示例如下:
import calendar
print(calendar.monthrange(2019, 10))
返回表示一个月的日历的矩阵,每一行代表一周,此月份外的日子由零表示,每周默认从周一开始,可使用 setfirstweekday() 改变默认值。示例如下:
import calendar
print(calendar.monthcalendar(2019,10))
打印由 month() 返回的一个月的日历,每日宽度间隔为 w 字符,l 是每星期的行数。示例如下:
import calendar
print(calendar.prmonth(2019,10))
打印由 calendar() 返回的整年的日历。示例如下:
import calendar
print(calendar.prcal(2019))
在当前的语言环境下表示星期几的列表。示例如下:
import calendar
print(calendar.day_name[0])
在当前语言环境下表示星期几缩写的列表。示例如下:
import calendar
print(calendar.day_abbr[0])
在当前语言环境下表示一年中月份的列表,一月的月号为 1,它的长度为 13 且 month_name[0] 是空字符串。示例如下:
import calendar
print(calendar.month_name[1])
在当前语言环境下表示月份简写的列表。示例如下:
import calendar
print(calendar.month_abbr[1])
Calendar 对象提供了一些可被用于准备日历数据格式化的方法,这个类本身不执行任何格式化操作,这部分任务应由子类来完成,下面具体看一下。
返回一个迭代器,迭代器的内容为一星期的数字。示例如下:
from calendar import Calendar
c=Calendar()
print(list(c.iterweekdays()))
返回一个迭代器,迭代器的内容为 year 年 month 月(1-12)的日期。示例如下:
from calendar import Calendar
c=Calendar()
print(list(c.itermonthdates(2019,10)))
返回一个迭代器,迭代器的内容与 itermonthdates() 类似为 year 年 month 月的日期,但不受 datetime.date 范围的限制,迭代器中的元素为一个由日期和代表星期几的数字组成的的元组。示例如下:
from calendar import Calendar
c=Calendar()
print(list(c.itermonthdays2(2019,10)))
返回一个迭代器,迭代器的内容与 itermonthdates() 类似为 year 年 month 月的日期,不受 datetime.date 范围的限制,迭代器的元素为一个由年、月、日组成的元组。示例如下:
from calendar import Calendar
c=Calendar()
print(list(c.itermonthdays3(2019,10)))
TextCalendar 对象提供了一些生成纯文本日历的方法,下面具体看一下。
返回一个多行字符串来表示指定年月的日历,w 为日期的宽度,始终保持日期居中,l 指定了每星期占用的行数;以上这些还依赖于构造器或者 setfirstweekday() 方法指定的周的第一天是哪一天。示例如下:
from calendar import TextCalendar
tc=TextCalendar()
print(tc.formatmonth(2019,10))
与 formatmonth() 方法一样,返回一个月的日历。示例如下:
from calendar import TextCalendar
tc=TextCalendar()
print(tc.prmonth(2019,10))
返回一个多行字符串,这个字符串为一个 m 列日历,可选参数 w、l、c 分别表示日期列数、周的行数、月之间的间隔;以上这些还依赖于构造器或者 setfirstweekday() 指定哪一天为一周的第一天。示例如下:
from calendar import TextCalendar
tc=TextCalendar()
print(tc.formatyear(2019))
与 formatyear() 方法一样,返回一整年的日历。示例如下:
from calendar import TextCalendar
tc=TextCalendar()
print(tc.pryear(2019))
HTMLCalendar 对象提供了一些生成 HTML 日历的方法,下面具体看一下。
返回一个 HTML 表格作为指定年月的日历,withyear 为 True,则年份将会包含在表头,否则只显示月份。示例如下:
from calendar import HTMLCalendar
hc=HTMLCalendar()
print(hc.formatmonth(2019,10))
返回一个 HTML 表格作为指定年份的日历,width 用于规定每一行显示月份的数量。示例如下:
from calendar import HTMLCalendar
hc=HTMLCalendar()
print(hc.formatyear(2019))
返回一个完整的 HTML 页面作为指定年份的日历,width 用于规定每一行显示的月份数量,css 为层叠样式表的名字,如果不使用任何层叠样式表,可以使用 None,encoding 为输出页面的编码 (默认为系统的默认编码)。示例如下:
家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
FullCalendar 是一个用于创建日历界面的 JavaScript 开源库,支持全尺寸拖放(Full-sized drag & drop),同时具有适用于 React 和许多其他框架的适配器,比如:React、Vue、Angular 、Web Component等以及一流的 TypeScript 支持。
FullCalendar 目前非常受欢迎 ,除了易于使用之外还具有许多内置功能和用于充分定制的插件,而官方提供的插件数量已经达到了 25+。
目前 FullCalendar 在 Github 上通过 MIT 协议开源,有超过 17.3k 的 star、3.6k 的 fork、项目依赖量 63.8k、代码贡献者 100+、妥妥的前端优质开源项目。
FullCalendar 库提供各种日历视图,例如:每月、每周和每天,还具有 TimeGrid 、 DayGrid 、TimeLine、Multi-Month Stack 等等视图模式,同时允许自定义视图,非常适合构建日程安排界面。
比如下面的代码设置了视图模式为 dayGridMonth:
import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
const calendar=new Calendar(calendarEl, {
plugins: [dayGridPlugin],
initialView: 'dayGridMonth',
});
页面渲染视图如下:
FullCalendar 具有多种用于添加额外功能的插件。
插件系统很有用,因为开发者不需要下载整个代码库,但可以选择要包含的插件。 这样做可以缩小代码库的大小,并使管理依赖项变得更容易。
一些主流的插件包括:
下面是在 Vue3 中使用 FullCalendar 的代码示例:
<script>
import FullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
export default {
components: {
FullCalendar
// make the <FullCalendar> tag available
},
data() {
return {
calendarOptions: {
plugins: [ dayGridPlugin, interactionPlugin ],
initialView: 'dayGridMonth'
}
}
}
}
</script>
<template>
<FullCalendar :options="calendarOptions" />
</template>
首先,需要安装核心 npm 包:
yarn add @fullcalendar/daygrid @fullcalendar/react
接下来,添加 FullCalendar 组件并包含日期网格插件:
import FullCalendar from '@fullcalendar/react';
import daygridPlugin from '@fullcalendar/daygrid';
export const MyCalendar=()=> {
return (
<div>
<FullCalendar plugins={[daygridPlugin]} />
</div>
);
};
下面是设置以后的基础视图:
接下来可以自定义顶部工具栏并添加每周和每日视图。 FullCalendar 提供了 headerToolbar 属性,开发者可以使用它来选择想要查看的控件:
<FullCalendar
headerToolbar={{
start: 'today prev next',
end: 'dayGridMonth dayGridWeek dayGridDay',
}}
plugins={[daygridPlugin]}
views={['dayGridMonth', 'dayGridWeek', 'dayGridDay']}
/>
headerToolbar 对象接受 start, center、end 字段 , 每个字段都必须是可以包含标题、上一个、下一个、上一年、下一年、今天和日历视图名称(如 dayGridMonth)的字符串。
开发者可以按照想要的任何顺序排列这些字段,FullCalendar 将正确的渲染。
为了给日历组件添加交互,需要首先添加 @fullcalendar/interaction 插件:
yarn add @fullcalendar/interaction
同时需要将 editable 和 selectable 属性设置为 true 并将事件处理程序放置在 events 属性中。
import FullCalendar from '@fullcalendar/react';
import daygridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import { useState } from 'react';
import { v4 as uuid } from 'uuid';
export const MyCalendar=()=> {
const [events, setEvents]=useState([]);
const handleSelect=(info)=> {
const { start, end }=info;
const eventNamePrompt=prompt('Enter, event name');
if (eventNamePrompt) {
setEvents([
...events,
{
start,
end,
title: eventNamePrompt,
id: uuid(),
},
]);
}
};
return (
<div>
<FullCalendar
editable
selectable
events={events}
// 事件处理
select={handleSelect}
headerToolbar={{
start: 'today prev next',
end: 'dayGridMonth dayGridWeek dayGridDay',
}}
plugins={[daygridPlugin, interactionPlugin]}
views={['dayGridMonth', 'dayGridWeek', 'dayGridDay']}
/>
</div>
);
};
以上代码首先添加了一个 handleSelect 回调,其接受 info 对象作为参数,该对象包含有关用户选择日期的信息。
Prompt() 函数向用户询问事件标题并创建一个包含开始、结束、标题和 ID 的新事件。而 id 属性需要是唯一的字符串,而这里引入了 uuid 三方库。
要添加编辑事件,可以遵循与上面类似的模式,只需要使用 eventClick 属性,而拖放操作则可以使用 eventChange 。
https://github.com/fullcalendar/fullcalendar
https://isamatov.com/react-fullcalendar-tutorial/
https://fullcalendar.io/docs/plugin-index
https://fullcalendar.io/docs/vue
https://medevel.com/os-js-calendar/
CodePen原项目Calendar
自己写个聚合首页,方便自己统一管理常用的网页工具,参考的是Mac OS的仪表盘,如下:
虽然短时间没法做到这么精美,但是起码功能得差不多吧,时钟与天气都已经OK,在做日历的时候觉得比较麻烦,就去CodePen找找看,便有了如此。
CodePen上的原项目本身难度不高,繁琐在理清楚日历逻辑(原作者逻辑),以及将此作者项目中关于DOM的操作转换成vue的模板操作。
先看逻辑
分别对应了原项目中这三个函数,原作者也有注释:
lastDayOfLastMonth 上个月最后一天,这里应该是原作者命名问题,应该是lastDayOfPreviousMonth
firstDayOfMonth 本月第一天
lastDateOfMonth 本月最后一天
i 是本月第几天,走了一个do while循环
上面的意思就是第一天时候把上个月尾巴给加到表格标签里面(最后统一加)
上面特殊处理的今天,其他本月内容都是常规加入,可以从class上面区分看出来。
上面的意思就是当本月最后一天的时候,顺便把下个月的月头加进来。
漏了,每行的首尾控制
这里说一下,因为日历是从周日到周六为一行,所以作者这里判断方案是Sunday与Saturday。
上面这些就是核心代码,当然还有下个月与上个月切换,不过就是清空当前日历再来一次,这些看源码即可,没有太多逻辑问题。
转vue
转起来难度不是很大,更多的是思维变化。
原项目是直接操作DOM,我们这里通过数据操作模板(姑且区分下),所以需要构建一个对象来承接每个”天“。
我们申明一个日历数组,由于日历是由若干个星期组成,所以我们就命名为:weeks,然后每个”天“给对象,属性如下:
那么我们的”天“会有这几种情况:
接下来,我们把原逻辑里面对应的html,换成weeks,tr换成week(每次新建一个空数组),在周日或者第一天时候把week置空,在周六或本月最后一天把week闭合并且让weeks来push一下week,循环走完,我们一个月的关于weeks、week以及”天“的处理就完成了。
核心逻辑如下:
注意跨年问题
最终效果
源码请直接看原作者项目,感谢阅读。
*请认真填写需求信息,我们会在24小时内与您取得联系。