我如何将年周(例如 0852 或 200852)转换为日期(例如 2008 年 12 月 31 日或特别是周末的一天,即星期六 2008 年 12 月 27 日或一周的开始日,即 2008 年 12 月 21 日) ? 周末的任何一天都可以,周五、周六、周日或周一。
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 设置为什么。
这是一个几乎独立于数据库的解决方案,如果这很重要的话。
创建一个名为 ALMANAC、主键 DATE 的表,其中列出了您计划使用的日期的所有属性。其中一个可能是 YEAR,另一个可能是 WEEK。您可以包含任何您想经常使用的 DATE 可计算函数。您还可以包括公司特定的 DATE 属性,例如该日期是否是公司假日。
编写一个程序来填充 DATE 比如说 10 年(大约 3650 行加上一些闰年)。该程序将使用 DBMS 或某些编程语言中可用的环境特定日期函数。一旦您填充了 ALMANAC 表,就可以像使用普通数据一样使用它。将主键与数据库中的任何日期字段连接起来。
事实证明,这对于按周、按月、按季度和按年几乎自动地准备报告等事情非常有用。
如果 DATE 的粒度不够细,您甚至可以将年历划分为更小的时间单位,例如 3 个班次为 1 天的班次。
为此,我创建了一个 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
日期函数几乎是特定于数据库的。例如,在 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 周的星期一)
在甲骨文中:
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
)
如果这是在 Oracle 中,请查看带有各种选项 YYYYWW 的 TO_Date 函数。从对偶中选择 TO_Date ('200852' YYYYWW);
http://www.oradev.com/oracle_date_format.jsp 一旦你得到一周的开始,你总是可以添加天数来获得周末日期。