【问题标题】:Get Date from ISO Week in SQL从 SQL 中的 ISO 周获取日期
【发布时间】:2018-02-25 01:45:18
【问题描述】:

我在 SQL 中创建了一个函数,以从“15W53”之类的格式返回 ISO 周的正确日期。其中“W”之前的第一部分是年份编号,后半部分是周编号。返回的日期应返回该日期的星期开始。

例如,15W53 应返回 12-28-2015,16W01 应返回 01-04-2016。但是,如果我为以下示例运行此程序,从我所读到的关于 ISO 周的内容中,我会得到不正确的结果。

我是否错误地创建了解析日期的函数?

SET DATEFIRST 1; 
SELECT dbo.[GetDateFromISOweek]('15W52') AS Correct, '15W52'  -- Returns: 2015-12-21
SELECT dbo.[GetDateFromISOweek]('15W53') AS Correct, '15W53'  -- Returns: 2015-12-28
SELECT dbo.[GetDateFromISOweek]('16W01') AS Incorrect, '16W01'-- Returns: 2015-12-28
SELECT dbo.[GetDateFromISOweek]('16W02') AS Incorrect, '16W02'-- Returns: 2016-01-04
SELECT dbo.[GetDateFromISOweek]('16W03') AS Incorrect, '16W03'-- Returns: 2016-01-11

功能:

CREATE FUNCTION [dbo].[GetDateFromISOweek] (@Input VARCHAR(10))  
RETURNS DATETIME  
WITH EXECUTE AS CALLER  
AS  
BEGIN  
    DECLARE @YearNum CHAR(4) 
    DECLARE @WeekNum VARCHAR(2)

    SET @YearNum = SUBSTRING(@Input,0,CHARINDEX('W',@Input,0))
    SET @WeekNum = SUBSTRING(@Input,CHARINDEX('W',@Input,0)+1,LEN(@Input))

    RETURN(DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNum) + (@WeekNum-1), 7));
END; 

【问题讨论】:

  • 我的建议是,任何时候你需要编写一个函数来计算一个日期,你应该考虑创建一个日期维度表。它会让你的生活轻松 1000%。 mssqltips.com/sqlservertip/4054/…
  • 嘿肖恩,这是个好主意!感谢您的链接!

标签: sql iso date-parsing


【解决方案1】:

更改您的回报中的 -1 以计算是否应考虑一年中的第一周(如果有超过 3 天)。 像这样的

case when DATEDIFF ( day ,  convert(datetime,'01/01/'+ @YearNum),@FirstDay )>=3 then 1 else 0 end

完整的代码,包括第一个星期日,可以改进,但工作......

CREATE FUNCTION [dbo].[GetDateFromISOweek] (@Input VARCHAR(10))  
RETURNS DATETIME  
WITH EXECUTE AS CALLER  
AS  
BEGIN  
    DECLARE @YearNum CHAR(4) 
    DECLARE @WeekNum VARCHAR(2)
    declare @FirstDay datetime

    SET @YearNum = cast(SUBSTRING(@Input,0,CHARINDEX('W',@Input,0)) as int)+2000
    SET @WeekNum = SUBSTRING(@Input,CHARINDEX('W',@Input,0)+1,LEN(@Input))
    set @FirstDay=DATEADD(DAY, (@@DATEFIRST - DATEPART(WEEKDAY, DATEADD(YEAR, @YearNum - 1900, 0)) +  (8 - @@DATEFIRST) * 2) % 7, DATEADD(YEAR, @YearNum - 1900, 0))-1

    RETURN(DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + @YearNum) + (@WeekNum-case when DATEDIFF ( day ,  convert(datetime,'01/01/'+ @YearNum),@FirstDay )>=3 then 1 else 0 end), 7));
END; 
go
SET DATEFIRST 1; 
SELECT dbo.[GetDateFromISOweek]('15W52'),'15W52' union
SELECT dbo.[GetDateFromISOweek]('15W53'),'15W53' union
SELECT dbo.[GetDateFromISOweek]('16W01'), '16W01' union
SELECT dbo.[GetDateFromISOweek]('16W02'), '16W02' union
SELECT dbo.[GetDateFromISOweek]('16W03'), '16W03'

结果是

----------------------- -----
2015-12-21 00:00:00.000 15W52
2015-12-28 00:00:00.000 15W53
2016-01-04 00:00:00.000 16W01
2016-01-11 00:00:00.000 16W02
2016-01-18 00:00:00.000 16W03

【讨论】:

  • 输入18W01 失败。此返回2018-01-08,预期结果为2018-01-01
猜你喜欢
  • 1970-01-01
  • 2011-08-18
  • 2015-01-11
  • 1970-01-01
  • 2010-10-11
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多