如何根据相应的工作日查找未来日期?

时间:2013-03-01 04:01:10

标签: sql-server tsql date calendar weekday

我正在开发一个日历系统,用于创建事件。我需要能够将任何事件(在一天内发生)“前滚”到用户指定的月/年。

例如,2013年3月4日是星期一。我需要能够根据给定的月/年确定相应的日期 - 基于工作日及其在月内的位置。因此,在这个例子中,4月的相应日期是4月1日,也就是星期一。

另一个例子:2013年3月13日是星期三,所以5月的相应日期是5月8日。

如果不是因为用户提供的月/年是可变的,那么这不是一项艰巨的任务;但既然是......

1 个答案:

答案 0 :(得分:1)

如果您的Dates表格包含五列,FullDateMonthDayYearDayOfWeek,则会填充随着日期的到来,你可以很容易地做到以下几点。

假设@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)

SQL Fiddle example

这有点难看,但它的作用是:

  1. @d的工作日与@firstSameDayInMonth相同的一个月的第一天。
  2. 确定哪一周#@d在其对应的月份内,作为基于0的整数@weekInMonth。这是@firstSameDayInMonth@d之间的周数。
  3. 获取@m年的第一天,@y年与@d相同的工作日进入@corrFirstSameDay
  4. 将基于0的周数@weekInMonth添加到@corrFirstSameDay以获得结果。
  5. 你可以做一个单行班吗?当然,只需替换你的变量。但是请注意,它很丑陋,除了缺乏可读性之外,真的没有什么可以获得的恕我直言:

    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)))