To Find the First Saturday of any month

  • wildh (8/12/2009)


    One thing to be mindful with - SET @dt = DATEADD(d,1-DAY(@dt),@dt) is that when it's used with getdate() the result includes the time as well as the date.

    Wildh,

    Good point, I'd overlooked that.

    Nigel

  • Nigel/Wildh,

    In my original post (768063), I convert the result to style 101 (mm/dd/yyyy), so it doesn't matter if @dt has a time or not.

    DECLARE @dt datetime

    SET @dt = GetDate()

    -- Change to first of the month

    SET @dt = DATEADD(d,1-DAY(@dt),@dt)

    IF DATEPART(dw,@dt) 7

    -- If not already Saturday, add a day until it is Saturday

    WHILE DATEPART(dw, @dt) 7

    SET @dt = DATEADD(d,1,@dt)

    PRINT CONVERT(nvarchar(30), @dt, 101)

    David

  • publicdh-tech (8/12/2009)


    Nigel/Wildh,

    In my original post (768063), I convert the result to style 101 (mm/dd/yyyy), so it doesn't matter if @dt has a time or not.

    David

    David,

    That is true in your example. I think, however, Wildh was talking more generally about that method of finding the first of the month.

    In many cases it may not matter at all that the time component is present, but there will be some when it does - (Sods Law). 🙂

    Nigel

  • Optimally, in SQL 2008, we would declare @dt as a date type instead of datetime and there would be no time issue. Then we would remove the CONVERT from the PRINT statement and the result would be a true date type instead of varchar.

  • declare @DayToFind tinyint, @AnyDayInAMonth datetime

    select @DayToFind = 1, --Monday

    @AnyDayInAMonth = '2009-04-15'--Target month

    select dateadd(day, (datepart(d, @AnyDayInAMonth) - datepart(dw, @AnyDayInAMonth) - @@datefirst + @DayToFind) % 7, dateadd(day, 1-datepart(d, @AnyDayInAMonth), @AnyDayInAMonth))

    Seems like a nice single-select statement to me.

  • nigel,

    That was what I was getting at.

    publicdh-tech,

    I like your point about 2008. Not being lucky enough to be using (or even testing) 2008 I'd not contemplated you can just use the date.

  • gerald.drouin (8/12/2009)


    declare @DayToFind tinyint, @AnyDayInAMonth datetime

    select @DayToFind = 1, --Monday

    @AnyDayInAMonth = '2009-04-15'--Target month

    select dateadd(day, (datepart(d, @AnyDayInAMonth) - datepart(dw, @AnyDayInAMonth) - @@datefirst + @DayToFind) % 7, dateadd(day, 1-datepart(d, @AnyDayInAMonth), @AnyDayInAMonth))

    Seems like a nice single-select statement to me.

    Gerald,

    There are some issues with your solution which you'll see if you set @AnyDayInAMonth to '2009-08-01'.

    The problem is with the expression:

    [font="Courier New"] datepart(d, @AnyDayInAMonth) - datepart(dw, @AnyDayInAMonth) - @@datefirst + @DayToFind[/font]

    which can yield a negative value in some cases.

    But still good to see an attempt using @@DATEFIRST to make the solution universal, without using loops, and without the horrible constant that I had in my solution.

    Nigel

  • Thanks for the catch on the negative numbers. I've added a 14 day offset to ensure the code always lands in the current month. Works for every day in 2009 now.

    declare @DayToFind tinyint, @AnyDayInAMonth datetime

    select @DayToFind = 1, --Monday

    @AnyDayInAMonth = '2009-04-15' --Target month

    select dateadd(day, (datepart(d, @AnyDayInAMonth) - datepart(dw, @AnyDayInAMonth) - @@datefirst + @DayToFind + 14) % 7, dateadd(day, 1-datepart(d, @AnyDayInAMonth), @AnyDayInAMonth))

  • gerald.drouin (8/13/2009)


    Thanks for the catch on the negative numbers. I've added a 14 day offset to ensure the code always lands in the current month. Works for every day in 2009 now.

    declare @DayToFind tinyint, @AnyDayInAMonth datetime

    select @DayToFind = 1, --Monday

    @AnyDayInAMonth = '2009-04-15' --Target month

    select dateadd(day, (datepart(d, @AnyDayInAMonth) - datepart(dw, @AnyDayInAMonth) - @@datefirst + @DayToFind + 14) % 7, dateadd(day, 1-datepart(d, @AnyDayInAMonth), @AnyDayInAMonth))

    Gerald,

    Yep, hopefully that does it. Was hoping to come up with a solution without that pesky constant 😉 but I've yet to find it. No doubt someone will, given the level of expertise here.

    Nigel

Viewing 9 posts - 16 through 23 (of 23 total)

You must be logged in to reply to this topic. Login to reply