我正在开发一个日历系统,用于创建事件。我需要能够将任何事件(在一天内发生)“前滚”到用户指定的月/年。
例如,2013年3月4日是星期一。我需要能够根据给定的月/年确定相应的日期 - 基于工作日及其在月内的位置。因此,在这个例子中,4月的相应日期是4月1日,也就是星期一。
另一个例子:2013年3月13日是星期三,所以5月的相应日期是5月8日。
如果不是因为用户提供的月/年是可变的,那么这不是一项艰巨的任务;但既然是......
答案 0 :(得分:1)
如果您的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)
这有点难看,但它的作用是:
@d
的工作日与@firstSameDayInMonth
相同的一个月的第一天。@d
在其对应的月份内,作为基于0的整数@weekInMonth
。这是@firstSameDayInMonth
和@d
之间的周数。@m
年的第一天,@y
年与@d
相同的工作日进入@corrFirstSameDay
。@weekInMonth
添加到@corrFirstSameDay
以获得结果。你可以做一个单行班吗?当然,只需替换你的变量。但是请注意,它很丑陋,除了缺乏可读性之外,真的没有什么可以获得的恕我直言:
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)))