5

我如何将年周(例如 0852 或 200852)转换为日期(例如 2008 年 12 月 31 日或特别是周末的一天,即星期六 2008 年 12 月 27 日或一周的开始日,即 2008 年 12 月 21 日) ? 周末的任何一天都可以,周五、周六、周日或周一。

4

6 回答 6

6

MS SQL SERVER 具有 DATEADD 功能,应该可以帮助...

DECLARE @date_string NCHAR(6)
SELECT  @date_string = N'200852'

SELECT DATEADD(
           WEEK,
           CAST(RIGHT(@date_string, 2) AS INT),
           DATEADD(
               YEAR,
               CAST(LEFT(@date_string, 4) AS INT) - 1900,
               0
           )
       )

编辑:

抱歉,错过了关于使它成为星期六等的一点...

一旦你有了这个值,使用 DATEPART 来得到它是星期几,然后从你的答案中减去它......

DECLARE @new_date DATETIME
SELECT  @new_date = '2008 Dec 30'

SELECT DATEADD(DAY, 1-DATEPART(dw, @new_date), @new_date)

这会将值带到一周的开始,具体取决于您将 DATEFIRST 设置为什么。

于 2009-02-03T12:50:23.770 回答
5

这是一个几乎独立于数据库的解决方案,如果这很重要的话。

创建一个名为 ALMANAC、主键 DATE 的表,其中列出了您计划使用的日期的所有属性。其中一个可能是 YEAR,另一个可能是 WEEK。您可以包含任何您想经常使用的 DATE 可计算函数。您还可以包括公司特定的 DATE 属性,例如该日期是否是公司假日。

编写一个程序来填充 DATE 比如说 10 年(大约 3650 行加上一些闰年)。该程序将使用 DBMS 或某些编程语言中可用的环境特定日期函数。一旦您填充了 ALMANAC 表,就可以像使用普通数据一样使用它。将主键与数据库中的任何日期字段连接起来。

事实证明,这对于按周、按月、按季度和按年几乎自动地准备报告等事情非常有用。

如果 DATE 的粒度不够细,您甚至可以将年历划分为更小的时间单位,例如 3 个班次为 1 天的班次。

于 2009-02-03T13:44:10.807 回答
5

为此,我创建了一个 UDF。
它将 YYYYWW 字符串或数字转换为日期。

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;

示例用法:

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;
山口 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

在这里测试db<>fiddle

ISO_WEEK 版本

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;
柱子 第一周 最后一周
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

在这里测试db<>fiddle

于 2021-12-02T12:53:49.920 回答
4

日期函数几乎是特定于数据库的。例如,在 MySQL 中,您可以执行以下操作以获取 'YYYYWW' 格式的一周中的星期一:

select date_sub(makedate(left('YYYYWW', 4), 1 + (right('YYYYWW', 2) - 1) * 7), 
interval weekday(makedate(left('YYYYWW', 4), 1 + (right('YYYYWW', 2) - 1) * 7)) DAY);

使用 makedate(left('YYYYWW', 4), 1 + (right('YYYYWW', 2) - 1) * 7) 你会得到一个绝对在给定周和年的日期,并且使用 date_sub 函数我们回到那周的星期一。

例子:

  • 对于“200906”,这将返回“2009-02-02”
  • 对于“200901”,它将返回“2008-12-29”(这实际上是 2009 年第 1 周的星期一)
于 2009-02-03T12:38:28.303 回答
3

在甲骨文中:

SELECT  TO_DATE('04.01.' || SUBSTR(iso, 1, 4)) + (TO_NUMBER(SUBSTR(iso, 5, 2))) * 7 - TO_CHAR(TO_DATE('04.01.' || SUBSTR(iso, 1, 4)), 'D')
FROM    (
    SELECT  '200101' AS iso
    FROM    dual
    )
于 2009-02-03T12:20:02.347 回答
3

如果这是在 Oracle 中,请查看带有各种选项 YYYYWW 的 TO_Date 函数。从对偶中选择 TO_Date ('200852' YYYYWW);

http://www.oradev.com/oracle_date_format.jsp 一旦你得到一周的开始,你总是可以添加天数来获得周末日期。

于 2009-02-03T12:25:47.860 回答