I need to calculate the year a week is assigned to. For example the 29th december of 2003 was assigned to week one of year 2004 (this is only for europe, I think). You can take a look at this with this code:
SELECT DATEPART(isowk, '20141229');
But now I need an easy way to get the year this week is assigned to. What I currently do is not that elegant:
DECLARE @week int, @year int, @date char(8)
--set @date = '20150101'
set @date = '20141229'
SET @week = cast(datepart(isowk, @date) as int)
if @week = 1
begin
if DATEPART(MONTH, @date) = 12
begin
set @year = DATEPART(year, @date) + 1
end
else
begin
set @year = DATEPART(year, @date)
end
end
select @date "DATE", @week "WEEK", @year "YEAR"
If anybody knew a more elegant way, that would be nice:-)
This solution does not return the correct value for the date '1-1-2027'
.
The following will return the correct value with all dates i tested (and i tested quite a few).
SELECT YEAR(DATEADD(day, 26 - DATEPART(isoww, '2012-01-01'), '2012-01-01'))
As taken from: https://capens.net/content/sql-year-iso-week
This is the most compact solution I could come up with:
CASE
WHEN DATEPART(ISO_WEEK, @Date) > 50 AND MONTH(@Date) = 1 THEN YEAR(@Date) - 1
WHEN DATEPART(ISO_WEEK, @Date) = 1 AND MONTH(@Date) = 12 THEN YEAR(@Date) + 1
ELSE YEAR(@Date) END
Can be used directly inside a SELECT statement. Or you could consider creating a user-defined function that takes the @Date parameter as input and outputs the result of the case statement.
I think Bart Vanseer solution is nice and simple, but off by 1. I believe it should be
select year(dateadd(day, 3 - ((datepart(weekday, @TestDate) + 5) % 7) , @TestDate))
Try following to find a few places were it differs
declare @TestDate date = '2000-01-01'
DECLARE @cnt INT = 0;
DECLARE @cnt_total INT = 10000;
WHILE @cnt < @cnt_total
BEGIN
SET @TestDate = dateadd(day,1, @TestDate)
if year(dateadd(day, 3 - (datepart(weekday, @TestDate) + 6) % 8, @TestDate)) <>
year(dateadd(day, 3 - ((datepart(weekday, @TestDate) + 5) % 7) , @TestDate))
BEGIN
select @TestDate, year(dateadd(day, 3 - (datepart(weekday, @TestDate) + 6) % 8, @TestDate))
select @TestDate, year(dateadd(day, 3 - ((datepart(weekday, @TestDate) + 5) % 7) , @TestDate))
END
SET @cnt = @cnt + 1;
END;
I think this solution is much more logical and easier to comprehend for ISO-8601.
"The first week of the year is the week containing the first Thursday." see ISO Week definition
So we need to deduct the weekday of the given date from Thursday and add this to that same date to get the year.
Edit: Adding 6 and then taking the modulus of 8 to move Sunday to the previous week.
declare @TestDate date = '20270101'
select year(dateadd(day, 3 - (datepart(weekday, @TestDate) + 6) % 8, @TestDate))
This will result in 2026 which is correct.
Inspired by the other answers, i came to the following solution:
declare @TestDate date = '20270101'
SELECT DATEPART(year, DATEADD(day, 4 - DATEPART(weekday, @TestDate), @TestDate))
Just get the thursday of the current week to get the correct year.
DECLARE @date DATETIME
SET @date='2014-12-29'
SELECT
CASE --Covers logic for ISO week date system which is part of the ISO 8601 date and time standard. Ref: https://en.wikipedia.org/wiki/ISO_week_date
WHEN (DATEPART(ISO_WEEK,@date) = 53) AND (DATEPART(MONTH,@date) = 1)
THEN CAST((DATEPART(YEAR, @date) - 1) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
WHEN (DATEPART(ISO_WEEK,@date) = 1) AND (DATEPART(MONTH,@date) = 12)
THEN CAST((DATEPART(YEAR,@date) + 1) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
ELSE CAST(DATEPART(YEAR,@date) AS varchar(4)) + ('-W') + CAST (RIGHT('0' + CAST(DATEPART(ISO_WEEK,@date) AS varchar(2)),2) AS varchar(2))
END AS ISO_week
对于 IsoYear,从 IsoWeek 获取星期四,然后获取年份。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.