如何找出給定日期的該週起始日期

網路上常有一些公開的行程表(schedule),一般會列出好幾筆最近的行程(可能橫跨過去現在未來的日期),如果要把這一週的行程做強調(highlight)的效果,我們勢必要知道一個日期(given date)在當週的頭(Week Begin Date)尾(Week End Date)日期。

上圖是 Roger Federer 的行程表,像是10月13號他在馬德里打球,我個人會比較傾向把這一行做強調,讓瀏覽者一眼就看的到他現在到底在哪打球,所以系統必須要能判斷現在的時間點是否要若在該行程那一週,若是有的話就顯示,沒有的話就找下一個賽事的行程。

拜了一下股溝大神之後,有神人在 2004 年就弄出來了,請參閱以下的連結:
Raj Chidipudi:Getting the Week Start Date and Week End Date in SQL
有一些很陌生的 SQL function,所以以下是自己加上的註解,若要改成 Stored Procedure 的話也是很簡單的,好用喔。


DECLARE @REPORT_DATE DATETIME, @WEEK_BEGINING VARCHAR(10)
SELECT @REPORT_DATE = '2008-10-13T00:00:00'
SELECT @WEEK_BEGINING = 'MONDAY'


這邊就是單純的宣告變數,@REPORT_DATE 就是我們所給予的日期(例如可以把費神的行程中任一天丟進去),而 @WEEK_BEGINING 則是我們告訴系統一星期開始的第一天是星期幾,你可以設定任一個星期,一般我是用星期天,那你只要把他改成 SUNDAY 就可以,純粹只是變數內容而已。


IF @WEEK_BEGINING = 'MONDAY' 
    SET DATEFIRST 1 
ELSE IF @WEEK_BEGINING = 'TUESDAY' 
    SET  DATEFIRST 2 
ELSE IF @WEEK_BEGINING = 'WEDNESDAY'
    SET  DATEFIRST 3 
ELSE IF @WEEK_BEGINING =  'THURSDAY'
    SET  DATEFIRST 4 
ELSE IF @WEEK_BEGINING =  'FRIDAY'
    SET  DATEFIRST 5 
ELSE IF @WEEK_BEGINING =  'SATURDAY'
    SET  DATEFIRST 6 
ELSE IF @WEEK_BEGINING =  'SUNDAY'
    SET  DATEFIRST 7 


接下來這個比較有趣,有一個 DATEFIRST,MSDN 中文版上的白話文是「將一週的第一天設為 1-7 其中一個數字」。所以如果你和我一樣設定成 SUNDAY 的話,這時候的 DATEFIRST 會是 7。


DECLARE @WEEK_START_DATE DATETIME, @WEEK_END_DATE DATETIME
--GET THE WEEK START DATE
SELECT  @WEEK_START_DATE = @REPORT_DATE - (DATEPART(DW,  @REPORT_DATE) - 1) 

--GET THE WEEK END DATE
SELECT  @WEEK_END_DATE = @REPORT_DATE + (7 - DATEPART(DW,  @REPORT_DATE))


上面的查詢句就是重點了,他的大意就是用使用者給定的日期去減掉 (運算式) 來對日期對往前或往後的動作。而 SELECT (DATEPART(DW, @REPORT_DATE) - 1) 這一句是指我給定的日期這一天是代表一個星期中的第幾天,由於是往前取日期,所以才預先 -1,所以反之如果要算該日期的當週最後一天的日期時,就是用 7 去減就可以得到值,再加上原本給定的日期,就會得到往後推遲幾天的日期了。DATEPART 中的 DW 是指 weekday,詳細說明請參閱這裡


PRINT 'Week Start: ' + CONVERT(VARCHAR, @WEEK_START_DATE)
PRINT 'Week End: ' + CONVERT(VARCHAR, @WEEK_END_DATE)


最後作者是列印出結果,當然你也可以把他改成 SELECT 這樣程式執行完 SP 後就可以得到這兩個起迄日期的值。

以上是自己的小小筆記,年紀大了需要寫下來才不會忘記,若是有相同情境的需求,這個 SP 應該可以適用喔 ^_^

0 comments: