首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >劳动节大战。感恩节

劳动节大战。感恩节
EN

Stack Overflow用户
提问于 2009-07-29 16:56:34
回答 5查看 1.9K关注 0票数 6

我正在为我的仓库创建一个日历表。我将把它用作所有日期字段的外键。

下面所示的代码创建并填充该表。我想出了如何找到阵亡将士纪念日(五月的最后一个星期一)和劳动节(九月的第一个星期一)。

代码语言:javascript
复制
SET NOCOUNT ON

DROP Table dbo.Calendar
GO
Create Table dbo.Calendar
(
    CalendarId              Integer NOT NULL,
    DateValue               Date    NOT NULL,
    DayNumberOfWeek         Integer NOT NULL,
    NameOfDay               VarChar (10) NOT NULL,
    NameOfMonth             VarChar (10) NOT NULL,
    WeekOfYear              Integer NOT NULL,
    JulianDay               Integer NOT NULL,
    USAIsBankHoliday        Bit     NOT NULL,
    USADayName              VarChar (100) NULL,
)
ALTER TABLE dbo.Calendar ADD CONSTRAINT
    DF_Calendar_USAIsBankHoliday DEFAULT 0 FOR USAIsBankHoliday
GO
ALTER TABLE dbo.Calendar ADD CONSTRAINT
    DF_Calendar_USADayName DEFAULT '' FOR USADayName
GO

Declare @StartDate  DateTime = '01/01/2000'
Declare @EndDate    DateTime = '01/01/2020'

While @StartDate < @EndDate
Begin
    INSERT INTO dbo.Calendar 
    (
        CalendarId, 
        DateValue, 
        WeekOfYear,
        DayNumberOfWeek,
        NameOfDay,
        NameOfMonth,
        JulianDay
    )
    Values 
    (
        YEAR (@StartDate) * 10000 + MONTH (@StartDate) * 100 + Day (@StartDate), --CalendarId
        @StartDate,                 -- DateValue
        DATEPART (ww, @StartDate),  -- WeekOfYear
        DATEPART (dw, @StartDate),  -- DayNumberOfWeek
        DATENAME (dw, @StartDate),  -- NameOfDay
        DATENAME (M, @StartDate),   -- NameOfMonth
        DATEPART (dy, @StartDate)   -- JulianDay
    )

    Set @StartDate += 1
End

--=========================== Weekends
-- saturday and sunday
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Weekend, ' WHERE DayNumberOfWeek IN (1, 7) 


--=========================== Bank Holidays
-- new years day
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'New Year''s Day, '  WHERE (CalendarId % 2000) IN (101)

-- memorial day (last Monday in May)
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Memorial Day, '  
WHERE 1=1
AND CalendarId IN 
    (
        SELECT MAX (CalendarId)
        FROM dbo.Calendar 
        WHERE MONTH (DateValue) = 5 
        AND DATEPART (DW, DateValue)=2
        GROUP BY YEAR (datevalue)
    )

-- independence day
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Independence Day, '  WHERE (CalendarId % 2000) IN (704)

-- labor day (first Monday in September)
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Labor Day, '  
WHERE 1=1
AND CalendarId IN 
    (
        SELECT MIN (CalendarId)
        FROM dbo.Calendar 
        WHERE MONTH (DateValue) = 9
        AND DATEPART (DW, DateValue)=2
        GROUP BY YEAR (datevalue)
    )

-- thanksgiving day (fourth Thursday in November)
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Thanksgiving Day, '  
WHERE 1=1
AND CalendarId IN 
    (
        SELECT Max (CalendarId)
        FROM dbo.Calendar 
        WHERE MONTH (DateValue) = 11
        AND DATEPART (DW, DateValue)=5
        GROUP BY YEAR (datevalue)
    )

-- christmas
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Christmas Day, '  WHERE (CalendarId % 2000) IN (1225)

--=========================== Other named days
-- new years eve
UPDATE dbo.Calendar SET USADayName += 'New Year''s Eve, '  WHERE (CalendarId % 2000) IN (1231)

-- christmas eve
UPDATE dbo.Calendar SET USADayName += 'Christmas Eve, '  WHERE (CalendarId % 2000) IN (1224)

-- boxing day
UPDATE dbo.Calendar SET USADayName += 'Boxing Day, '  WHERE (CalendarId % 2000) IN (1226)

--=========================== Remove trailing comma
UPDATE dbo.Calendar SET USADayName = SubString (USADayName, 1, LEN (USADayName) -1) WHERE LEN (USADayName) > 2

SELECT * FROM dbo.Calendar

我很难计算出感恩节(11月最后一周的星期四)。

编辑:基于John 评论的修正

感恩节是十一月的第四个星期四。然而,经过几年的检查,我发现这也是11月11日最后一周的星期四。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-07-29 16:57:48

我很难搞清楚感恩节(11月最后一周的星期四)。

十一月二日上星期六

票数 16
EN

Stack Overflow用户

发布于 2009-07-29 16:58:30

取11月的最后一个星期六,减去两天;)

票数 6
EN

Stack Overflow用户

发布于 2009-07-29 17:04:10

代码语言:javascript
复制
WITH    cal AS
        (
        SELECT  CAST('2009-30-11' AS DATETIME) AS cdate
        UNION ALL
        SELECT  DATEADD(day, -1, cdate)
        FROM    cal
        WHERE   cdate >= '2009-01-11'
        )
SELECT  TOP 1 DATEADD(day, -2, cdate)
FROM    cal
WHERE   DATEPART(weekday, cdate) = 6

对于复杂的算法,有时从集合中找到匹配日期比试图构造一个庞大的单值公式要好。

有关更多细节,请参阅我博客中的这篇文章:

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1201643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档