我正在开发一个创建事件的日历系统。我需要能够将任何事件(在一天内发生)“前滚”到用户指定的月/年。
例如,2013 年 3 月 4 日是星期一。我需要能够根据给定的月份/年份确定相应的日期 - 基于工作日及其在月份中的位置。因此,在此示例中,4 月的对应日期为 4 月 1 日,即星期一。
另一个例子:2013 年 3 月 13 日是星期三,所以 5 月的对应日期是 5 月 8 日。
如果不是因为用户提供的月/年是可变的,这将不是那么困难的任务;但既然是...
我正在开发一个创建事件的日历系统。我需要能够将任何事件(在一天内发生)“前滚”到用户指定的月/年。
例如,2013 年 3 月 4 日是星期一。我需要能够根据给定的月份/年份确定相应的日期 - 基于工作日及其在月份中的位置。因此,在此示例中,4 月的对应日期为 4 月 1 日,即星期一。
另一个例子:2013 年 3 月 13 日是星期三,所以 5 月的对应日期是 5 月 8 日。
如果不是因为用户提供的月/年是可变的,这将不是那么困难的任务;但既然是...
如果您有一个Dates包含五列、FullDate、Month、Day、Year和的表DayOfWeek,并填充了未来的日期,您可以轻松地执行以下操作。
假设@m和@y是用户指定的前滚月/年,@d是事件日期:
DECLARE @weekNumInMonth int =
(
SELECT COUNT(1)
FROM Dates
WHERE Year = datepart(year @d)
AND Month = datepart(month, @d)
AND DayOfWeek = datepart(weekday, @d)
AND Day <= datepart(day, @d)
)
SELECT MAX(FullDate)
FROM
(
SELECT TOP @weekNumInMonth
FROM Dates
WHERE Year = @y
AND Month = @m
AND DayOfWeek = datepart(weekday, @d)
) x
如果没有日期表,您只需要做一些数学运算:
DECLARE @DOW int = datepart(weekday, @d)
DECLARE @firstDayInMonth date = dateadd(day, 1-datepart(day, @d), @d)
DECLARE @firstDayInMonthDOW int = datepart(weekday, @firstDayInMonth)
DECLARE @firstSameDayInMonth date =
dateadd(day, (7-(@firstDayInMonthDOW-@DOW))%7, @firstDayInMonth)
DECLARE @weekInMonth int = datediff(week, @firstSameDayInMonth, @d)
DECLARE @corr date = datefromparts(@y, @m, 1)
DECLARE @corrDOW int = datepart(weekday, @corr)
DECLARE @corrFirstSameDay date = dateadd(day, (7-(@corrDOW-@DOW))%7, @corr)
SELECT dateadd(week, @weekInMonth, @corrFirstSameDay)
这有点难看,但它的作用是:
@dinto相同@firstSameDayInMonth。@d以从 0 开始的整数形式确定相应月份内的第 # 周@weekInMonth。这是 和 之间的周@firstSameDayInMonth数@d。@m, year @y with the same weekday as @d into @corrFirstSameDay.@weekInMonth to @corrFirstSameDay to get the result.Can you do it as a one-liner? Sure, just substitute your variables. Be warned though, it's ugly, and there's really nothing to be gained from it except lack of readability IMHO:
SELECT dateadd(week, datediff(week, dateadd(day, (7-(datepart(weekday, dateadd(day,
1-datepart(day, @d), @d))-datepart(weekday, @d)))%7, dateadd(day,
1-datepart(day, @d), @d)), @d), dateadd(day, (7-(datepart(weekday,
datefromparts(@y, @m, 1))-datepart(weekday, @d)))%7, datefromparts(@y, @m, 1)))