在寫日歷組件和旅行相關頻道開發的過程中,很多需要地方需要和日期對象打交道。拿京東旅游首頁來說, 左上角的搜索框就包含了許多日期相關的交互邏輯,它包含了機票,酒店,度假等,這些都含有出發日期,到達日期等。

里面還包含了一個日期組件,在用戶選擇完出發日期后,會自動把到達日期定位在出發日期的下一天。

又如機票低價日歷

還有度假的這種特殊日歷

以下是經常需要用到日期相關小函數
一、 判斷閏年
這個函數在日歷組件是必須要的,閏年的2月是29天,非閏年是28天
/*
* 判斷閏年
* @param {Number} 年
* @return {Blooean}
*/
function isLeapYear(year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}
isLeapYear(2015) // false
isLeapYear(2016) // true
二、補齊月,日數字位數
通過Date對下的getMonth,getDate返回的數字如果是10以下的需要在前面補齊一個0。這里需要注意的是getMonth返回的月份是從0開始的,即0代表1月份,1代表2月份,依次類推。
/*
* 補齊月,日數字位數
* @param {number|string} n 需要補齊的數字
* @return {string} 補齊兩位后的字符
*/
function getTwoBit(n) {
return (n > 9 ? '' : '0') + n
}
getTwoBit(3) // '03'
getTwoBit(9) // '09'
getTwoBit(10) // '10'
getTwoBit(11) // '11'
三、Date對象轉成日期格式字符串
有兩種格式"2015-01-22" 和 "2015/01/23"
/*
* 日期對象轉成字符串
* @param {Date} new Date()
* @split {String} "-" 或 "/"
* @return {String} "2014-12-31"
*/
function date2Str(date, split) {
split = split || '-'
var y = date.getFullYear()
var m = getTwoBit(date.getMonth() + 1)
var d = getTwoBit(date.getDate())
return [y, m, d].join(split)
}
四、日期格式字符串轉成Date對象
/*
* 日期字符串轉成Date對象
* @param {String} str
* "2014-12-31"
* "2014/12/31"
* @return {Date}
*/
function str2Date(str) {
var reDate = /^\d{4}\-\d{1,2}\-\d{1,2}/
if (reDate.test(str)) {
str = str.replace(/-/g, '/')
}
return new Date(str)
}
這里需要注意下,不能直接 new Date('2014-12-31'),橫線間隔的日期格式字符串作為參數傳給Date構造器不是所有瀏覽器都支持。
五、根據數字返回特定的天
比如旅行頻道出發日期一般是第二天(明天),返程日期是第三天(后天)

這個函數根據數字返回特定的日期字符串
/*
* 返回日期格式字符串
* @param {Number} 0返回今天的日期、1返回明天的日期,2返回后天得日期,依次類推
* @return {string} '2014-12-31'
*/
function getSpecDay(i) {
i = i || 0
var date = new Date
var diff = i * (1000 * 60 * 60 * 24)
date = new Date(date.getTime() + diff)
return date2Str(date)
}
getSpecDay(0) // 2014-12-31
getSpecDay(1) // 2015-01-01
六、根據Date對象獲取星期
有的需求要顯示的是 “周三”,有的則是 “星期三”
/*
* 根據Date對象獲取周幾
* @param date {Date|String} 如 '2014-12-22'
* @param isFormal {Boolean}
* @return '周一' 或 '星期一'
*/
function getWeekByDate(date, isFormal) {
var obj = null
var weekArr1 = ['周日','周一','周二','周三','周四','周五','周六']
var weekArr2 = ['星期日', '星期一','星期二','星期三','星期四','星期五','星期六']
if (typeof date == 'string') {
obj = str2Date(date)
} else if (date instanceof Date) {
obj = date
}
var num = obj.getDay()
return isFormal ? weekArr2[num] : weekArr1[num]
}
七、根據年獲取生肖
/*
* 根據年獲取生肖
*
* **參數**
* year {number} 年
*
* **示例**
* getAnimal(1980) // "猴"
* getAnimal(1981) // "雞"
* getAnimal(2013) // "蛇"
*/
function getAnimal(year) {
var animals = ['鼠', '牛', '虎', '兔', '龍', '蛇', '馬', '羊', '猴', '雞', '狗', '豬'];
var i = (year - 4) % 12;
return animals[i];
}
八、根據年月返回該月的兩個節氣,一個公歷月有兩個節氣
/*
* 根據年月返回該月的兩個節氣,一個公歷月有兩個節氣
*
* **節氣算法**
* http://ershisijieqi.baike.com/article-284624.html
* http://www.azg168.com/huangli/24sijieqi/28337.html
* http://blog.csdn.net/orbit/article/details/7910220
*
* **參數**
* year {number} 年
* month {number} 月
*
* **返回**
* object
*
* **示例**
* getSolarTerm(2016, 4); // {day1: 4, term1: "清明", day2: 19, term2: "谷雨"}
*
*/
function getSolarTerm(year, month) {
var solarTerm = [
"小寒", "大寒",
"立春", "雨水",
"驚蟄", "春分",
"清明", "谷雨",
"立夏", "小滿",
"芒種", "夏至",
"小暑", "大暑",
"立秋", "處暑",
"白露", "秋分",
"寒露", "霜降",
"立冬", "小雪",
"大雪", "冬至"
];
var termInfo = [
0, 21208, 42467, 63836, 85337, 107014,
128867, 150921, 173149, 195551, 218072,
240693, 263343, 285989, 308563, 331033,
353350, 375494, 397447, 419210, 440795,
462224, 483532, 504758
];
// 返回某年的第n個節氣為幾日(從0小寒起算)
function computeTermDay(y, n) {
var d = new Date((31556925974.7 * (y - 1900) + termInfo[n] * 60000) + Date.UTC(1900, 0, 6, 2, 5));
return d.getUTCDate();
}
// month 轉為 [0-11] 范疇
month = month - 1;
// 計算節氣
var n1 = month * 2;
var n2 = month * 2 + 1;
// day1, day2 為當月的兩個節氣日
var day1 = computeTermDay(year, n1);
var day2 = computeTermDay(year, n2);
// 當月的兩個節氣名稱
var term1 = solarTerm[n1];
var term2 = solarTerm[n2];
// 返回結果
return {
day1: day1,
term1: term1,
day2: day2,
term2: term2
};
}
九、獲取Y年的清明節是哪一天
/*
* 獲取Y年的清明節是哪一天
*
* **參數**
* yare {number} 年
*
* **示例**
* getQingMing(2015); // 0405
* getQingMing(2016); // 0404
*/
function getQingMing(year) {
// [Y*D+C]-L
// Y=年數后2位,D=0.2422,L=閏年數,21世紀C=4.81,20世紀=5.59
var d = 0.2422;
var c = 4.81;
var y = (year + '').substr(2);
var day = parseInt(y*d+c) - parseInt(y/4);
return day;
}
