I've created a UDF for this purpose.
It'll convert a YYYYWW string or number to a date.
CREATE FUNCTION dbo.GetDateFromYearWeek (
@YearWeek VARCHAR(7) = '000101', -- default
@WeekDay INT = 1, -- default
@FirstWeekDayName VARCHAR(9) = 'mon' -- default
) RETURNS DATE
BEGIN
IF @YearWeek = '000101'
SET @YearWeek = CONCAT(DATEPART(year, GETDATE()), '-', DATEPART(week, GETDATE()));
IF @YearWeek NOT LIKE '[0-9][0-9][0-9][0-9]%[0-9-][0-9]'
RETURN NULL;
IF @WeekDay < 1 OR @WeekDay > 7
RETURN NULL;
DECLARE @FirstWeekDay INT = CHARINDEX(LOWER(LEFT(@FirstWeekDayName,3)), ' montuewedthufrisatsun')/3;
IF @FirstWeekDay = 0 -- not found in string
SET @FirstWeekDay = @@DATEFIRST;
DECLARE @Year INT = TRY_CAST(LEFT(@YearWeek, 4) AS INT);
DECLARE @Week INT = ABS(TRY_CAST(RIGHT(@YearWeek, 2) AS INT));
DECLARE @Date DATE = TRY_CAST(CONCAT(@Year,'-01-01') AS DATE);
SET @Date = DATEADD(week, @Week-1, @Date);
DECLARE @DowDiff INT = (6-@FirstWeekday+@@DATEFIRST+DATEPART(weekday,@Date))%7;
SET @Date = DATEADD(day, -@DowDiff, @Date);
SET @Date = DATEADD(day, @WeekDay-1, @Date);
RETURN @Date;
END;
Example usage:
SELECT *
, [StartOfWeek_SundayFirst] = dbo.GetDateFromYearWeek(col, 1, 'sun')
, [StartOfWeek_MondayFirst] = dbo.GetDateFromYearWeek(col, 1, 'mon')
, [EndOfWeek_SundayFirst] = dbo.GetDateFromYearWeek(col, 7, 'sunday')
, [EndOfWeek_MondayFirst] = dbo.GetDateFromYearWeek(col, 7, 'monday')
FROM (VALUES (202201), (202202)) q(col)
ORDER BY 1;
col |
StartOfWeek_SundayFirst |
StartOfWeek_MondayFirst |
EndOfWeek_SundayFirst |
EndOfWeek_MondayFirst |
202201 |
2021-12-26 |
2021-12-27 |
2022-01-01 |
2022-01-02 |
202202 |
2022-01-02 |
2022-01-03 |
2022-01-08 |
2022-01-09 |
Test it on the db<>fiddle here.
ISO_WEEK Version
CREATE FUNCTION dbo.GetDateFromIsoYearWeek (
@YearWeek VARCHAR(7) = '0000-00', -- default
@WeekDay INT = 1 -- default
) RETURNS DATE
BEGIN
IF @YearWeek = '0000-00'
SET @YearWeek = CONCAT(DATEPART(year, GETDATE()), '-', DATEPART(iso_week, GETDATE()));
IF @YearWeek NOT LIKE '[0-9][0-9][0-9][0-9]%[0-9-][0-9]'
RETURN NULL;
IF @WeekDay < 1 OR @WeekDay > 7
RETURN NULL;
DECLARE @FirstWeekDay INT = 1; -- monday
DECLARE @Year INT = TRY_CAST(LEFT(@YearWeek, 4) AS INT);
DECLARE @Week INT = ABS(TRY_CAST(RIGHT(@YearWeek, 2) AS INT));
DECLARE @Date DATE = TRY_CAST(CONCAT(@Year,'-01-08') AS DATE);
SET @Date = DATEADD(week, @Week - 2 + (DATEPART(week, @Date)-(DATEPART(iso_week, @Date))), @Date);
DECLARE @DowDiff INT = (6-@FirstWeekday+@@DATEFIRST+DATEPART(weekday,@Date))%7;
SET @Date = DATEADD(day, -@DowDiff, @Date);
SET @Date = DATEADD(day, @WeekDay-1, @Date);
RETURN @Date;
END;
DECLARE @Test TABLE ([column] char(7));
INSERT INTO @Test VALUES
('2020-53'), ('2021-01'), ('2021-02')
, ('2021-48')
, ('2021-53'), ('2022-01'), ('2022-02')
;
SELECT [column]
, [FirstOfWeek] = dbo.GetDateFromIsoYearWeek([column], 1)
, [LastOfWeek] = dbo.GetDateFromIsoYearWeek([column], 7)
FROM @Test
ORDER BY 1;
column |
FirstOfWeek |
LastOfWeek |
2020-53 |
2020-12-28 |
2021-01-03 |
2021-01 |
2021-01-04 |
2021-01-10 |
2021-02 |
2021-01-11 |
2021-01-17 |
2021-48 |
2021-11-29 |
2021-12-05 |
2021-53 |
2022-01-03 |
2022-01-09 |
2022-01 |
2022-01-03 |
2022-01-09 |
2022-02 |
2022-01-10 |
2022-01-16 |
Test it on the db<>fiddle here.