我知道年份和周数,例如
year = 2016
week = 1
根据 ISO 8601 ,如何从中获取一周的第一天?
我在表datetime2[0]
日期类型中生成默认值2015-12-28
,但一周的第一天应为2016-01-04
任何想法?
答案 0 :(得分:2)
给定任何日期,此SQL将返回ISO周:SELECT DATEPART(ISO_WEEK, @date)
。下面是计算该ISO周的第一个日期的丑陋(但非常有效)的方法:
DECLARE @date DATETIME = '2012-09-16'
SELECT (
CASE DATEPART(ISO_WEEK, @date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-6,@date)) THEN DATEADD(DAY,-6,@date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-5,@date)) THEN DATEADD(DAY,-5,@date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-4,@date)) THEN DATEADD(DAY,-4,@date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-3,@date)) THEN DATEADD(DAY,-3,@date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-2,@date)) THEN DATEADD(DAY,-2,@date)
WHEN DATEPART(ISO_WEEK, DATEADD(DAY,-1,@date)) THEN DATEADD(DAY,-1,@date)
ELSE DATEADD(DAY,0,@date)
END
) FirstDayOfISOWeek
现在,这不是我最漂亮的作品,但它是通过反复试验而起作用的-测试多少周前的ISO周仍然是相同的,然后返回这一天。
答案 1 :(得分:1)
我认为处理业务数据最好的办法是将其存储在表格中。 ISO周是业务数据。如果你有一个看起来像这样的表
calendar_date iso_year iso_week -- 2016-01-01 2015 53 2016-01-02 2015 53 2016-01-03 2015 53 2016-01-04 2016 1 2016-01-05 2016 1 2016-01-06 2016 1 2016-01-07 2016 1
然后回答问题"什么是2016年ISO第1周的第一个日期?"简化为此。
select min(calendar_date)
from calendar
where iso_year = 2016;
and iso_week = 1;
以下是如何创建这样的表格。 (未经过严格测试。)
create table calendar (
calendar_date date primary key,
iso_year integer not null,
iso_week integer not null,
check (iso_week = datepart(iso_week, calendar_date)),
check (iso_year = year(dateadd(wk, datediff(d, 0, calendar_date) / 7, 3)))
);
此代码将填充它。
declare @start_date date;
select @start_date = '2016-01-01';
declare @end_date date;
select @end_date = '2050-12-31';
declare @next_date date;
select @next_date = (select coalesce(max(calendar_date), @start_date) from calendar);
while @next_date <= @end_date
begin
begin transaction;
insert into calendar values (@next_date , year(dateadd(wk, datediff(d, 0, @next_date) / 7, 3)), datepart(iso_week, @next_date));
commit;
select @next_date = dateadd(d, 1, @next_date);
end
小心控制权限。很少有人应该拥有插入,更新或删除权限。
答案 2 :(得分:0)
CLR功能也是一种可能性
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Globalization;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static DateTime fnFirstDateOfWeekISO8601(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = DayOfWeek.Thursday - jan1.DayOfWeek;
DateTime firstThursday = jan1.AddDays(daysOffset);
var cal = CultureInfo.CurrentCulture.Calendar;
int firstWeek = cal.GetWeekOfYear(firstThursday, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
var weekNum = weekOfYear;
if (firstWeek <= 1)
{
weekNum -= 1;
}
var result = firstThursday.AddDays(weekNum * 7);
return result.AddDays(-3);
}
}