最近出了一個面試題,
給一個時間,獲取這個月的結束的日期。比如 輸入'2018-08-04' 輸出'2018-08-31'
這個題目,相應如果熟悉php date
的應該很快能寫出來。但是遇到一些求職者,可能沒思考清楚,於是就開始編寫了。
一個月的結束時間,只要知道這個月有多少天,就能知道最後一天是多少號了?但是這裡你要思考的問題就有很多,因為月份有大小月份(1 3 5 7 8 10 12 則是大月有31天,其餘的月份除了2月,都是小月,每個月有30天),你可能會忽略掉2月這個特殊的月份,因為2月又有29天和28天。假設你已經考慮到2月了,但是你又得需要考慮閏年了,閏年的規則你需要知道吧!
不考慮超大年的情況下的規則(按照曆法 比如 3200 就不是閏年。有興趣的可以查下資料)
普通年:能被4整除但不能被100整除的年份為普通閏年。(如2004年就是閏年,1999年不是閏年);
世紀年:能被400整除的為世紀閏年。(如2000年是閏年,1900年不是閏年);
於是有的求職者上來就寫了一個這種程式碼
方法一
function monthDay($date) {
$month31 = [1, 3, 5, 7, 8, 10, 12];
list($year, $month) = explode('-',$date);
if ($month != 2) {
if (in_array($month, $month31)) {
return "{$year}-{$month}-31";
} else {
return "{$year}-{$month}-30";
}
}
if ( $year%4==0 && ($year%100!=0 || $year%400==0 ) ){
return "{$year}-{$month}-29";
}else{
return "{$year}-{$month}-28";
}
}
方法二
方法一的程式碼看著沒啥問題,但是可能是一種特別複雜的實現方式,它考慮的因素比較多。
我們可以換種思考的方式,這個月有多少天,我們知道一個月的開始時間和一個月的結束時間 兩者相減,也是等於當月的天數。一月末正好是一個月的開始。而且每個月的開始時間是固定的,都是1號,不會變的。下一個月的月數等於當月+1。
但是有個特殊的情況,如果是年底,那麼12月的下一月就是新的一年的1月。
function endDayOfMonth($date) {
list($year, $month) = explode('-',$date);
$nextYear = $year;
$nexMonth = $month+1;
//如果是年底12月 下個月就是1月
if($month == 12) {
$nexMonth = "01";
$nextYear = $year+1;
}
$begin = "{$year}-{$month}-01 00:00:00";
$end = "{$nextYear}-{$nexMonth}-01 00:00:00";
$day = (strtotime($end) - strtotime($begin) )/ (24*60*60);
return "{$year}-{$month}-{$day}";
}
方法三
方法二的方法其實已經差不多接近了,但是還是可能不夠特別好的。因為我們不需要算天數。我們知道新的一個月的第一天,減去一個1,就是當月的最後一秒。
function endDayOfMonth($date) {
list($year, $month) = explode('-',$date);
$nextYear = $year;
$nexMonth = $month+1;
//如果是年底12月 下個月就是1月
if($month == 12) {
$nexMonth = "01";
$nextYear = $year+1;
}
$end = "{$nextYear}-{$nexMonth}-01 00:00:00";
$endTimeStamp = strtotime($end) - 1 ;
return date('Y-m-d',$endTimeStamp);
}
PHP自帶函式實現
其實php自帶的有多種實現的方式,比如date、DateTime、strtotime等
- php date 函式格式化
t
指定月份的天數; 如: "28" 至 "31"$date = '2018-08-08'; echo date('Y-m-t',strtotime($date));
- strtotime 字串時間修飾詞
last day of this month
時間字元 類似我們常說的 -1 dayecho date('Y-m-d',strtotime("last day of this month",strtotime('2018-02-01'))); echo date('Y-m-d',strtotime("last day of 2018-02"));
-
php DateTime類 物件導向方式
$date = new \DateTime('2000-02-01'); $date->modify('last day of this month'); echo $date->format('Y-m-d');
其實這題主要是我們常見的面試題演變的。主要是想看怎麼考慮問題,很多的時候,我們陷入了一個誤區裡,考慮了複雜的實現,其實就是兩個函式的使用,一個是 date
和 strtotime
求昨天的日期,strtotime('-1 day')
能使用date("Y-m-t")
的這種是最簡單的,題目中沒有提到不用內建函式,所以也考慮思考的方式,是否讀了題目,就跟我們以前考試一樣。做選擇題,從下面選項選出不是的答案,我們看了第一個正確就選了。
想法很重要!