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小時內與您取得聯系。