【问题标题】:Efficent way to set date using week of month value使用月份值设置日期的有效方法
【发布时间】:2009-05-12 13:46:30
【问题描述】:

我在 sql 中有一个月的一周,我需要从中生成一个日期时间变量。我拥有的字段是 dayofweek、weekofmonth 和月份值。有人知道在 mssql 2005 中快速有效的计算方法吗?谢谢

请记住。如果将月份的周数设置为 5,则表示该月的最后一周

例如我有 DayOfWeek、month、year、weekofmonth..

所以可以说我有 DayOfWeek = 2(星期一) 月 = 5(五月) 年 = 2009 weekofmonth = 5

我预计 2009 年 5 月 25 日星期一

DayOfWeek = 1,月 = 5,周 = 1,年 = 2009 = 2009 年 5 月 3 日,星期日

DayOfWeek = 5,Month = 4,Week = 3,Year = 2009 = 2009 年 4 月 16 日,星期四

附加信息:

我正在使用 .net TimezoneInfo.TransitionTime 类库来帮助我在数据库中存储一些东西。他们说:

Month 属性定义时间更改发生的月份。 Day 属性定义发生转换的星期几。 Week 属性确定时间更改发生在一个月中的哪一周。Week 属性的有效值范围为 1 到 5。值 5 表示该月的最后一周。

到目前为止我有这个:

declare @IsFixedDateRule    bit
declare @Day                tinyint
declare @DayOfweek          tinyint
declare @Week               tinyint
declare @Month              tinyint
declare @Year               int
declare @TimeofDay          int -- SECONDS

set @IsFixedDateRule = 0
set @Day = 1
set @DayOfweek = 1
set @Week = 5
set @Month = 4
set @year = 2008
set @TimeofDay = 7200

declare @date datetime

if (@IsFixedDateRule = 1)   
begin
    set @date = convert(char(4),@Year) + '/' + convert(char(2),@Month) + '/' + convert(char(2),@Day)  -- Set Year/Month
end
else
begin       
    set @date = convert(char(4),@Year)  + '/' + convert(char(2),@Month) + '/01' -- Set Year/Month

    declare @datepart tinyint
    set @datepart = datepart(weekday ,@date)    

    set @date = dateadd(week, @week - 1, dateadd(weekday, @Dayofweek - case when @datepart = 7 then 0 else @datepart end, @date))-- get the day

end

select dateadd(second, @TimeofDay,  @date) -- Add Time Of Day

有什么更清洁的吗?

【问题讨论】:

  • 提供一些例子(多个)。给定 x, y, z, 结果是 g....
  • 您能否再发布一些示例(例如,什么是 dayofweek=1、weekofmonth=1、month=5、year=2009)。今年 8 月有 6 周……你的第 5 周是最大值吗?如果是,您将如何表示 8 月 31 日,以使其与 8 月 24 日不同?
  • 当然..您的示例将显示 2009 年 5 月 3 日星期日.. 我将编辑我的帖子以包含更多信息
  • 如果 dayofweek=1, weekofmonth=1, month=5 是 5 月 3 日,如何表示 5 月 1 日?
  • 这个例子只涵盖了没有固定时间表的日期。固定日期处理得更干净。这通常处理像四月的第三个星期三这样的日期。等等。在你的例子中,我们需要做的第一个可能.. 月 = 5 dayofweek = 6 (fri) week = 1 year = 2009

标签: sql-server sql-server-2005 datetime date


【解决方案1】:

这相当简单,实际上只是在该月的第一天增加了几天和几周。它假设您使用的是当前年份,并且不会真正处理像二月的第 5 周这样的事情。 (例如:第 5 周,2 月的第 3 天给出 03/11/2009)

DECLARE @CalculatedDate DATETIME;

-- Assuming DayOfWeek and WeekOfMonth are 1-based
SELECT @CalculatedDate = DATEADD(DAY, @DayOfWeek - 1, DATEADD(WEEK, @WeekOfMonth - 1, '2009-' + STR(@Month) + '-01'));

-- Assuming DayOfWeek and WeekOfMonth are 0-based
SELECT @CalculatedDate = DATEADD(DAY, @DayOfWeek, DATEADD(WEEK, @WeekOfMonth, '2009-' + STR(@Month) + '-01')) 

它还假设 DayOfWeek == 1 表示该月的第一天,所以它几乎肯定是错误的。我们可以看到一些示例数据和预期输出吗?

【讨论】:

  • 感谢您的建议g.. 工作完美,除非 weekofmonth 设置为 5.. 应该是该月的最后一周.. 这会溢出到下个月
【解决方案2】:

五月的第一周从星期五开始。那么 dayofweek=1、weekofmonth=1、month=5 是哪一天呢?是 4 月 27 日星期一吗?

【讨论】:

    【解决方案3】:
    /* 
     * Assuming @year is this year
     *          @day_of_week starts from Sunday = 1, Monday = 2 etc
     */
    declare @week_of_month int,
            @day_of_week int,
            @month int,
            @year int,
            @derived_date datetime
    
    set dateformat dmy
    select @year = datepart(year, getdate()),
           @day_of_week = 2,
           @week_of_month = 2,
           @month = 5
    
    
    select @derived_date = convert(varchar,@year) + '-01-' + convert(varchar,@month) 
    select @derived_date
    select @derived_date = dateadd(dd, @day_of_week - datepart(dw, @derived_date), dateadd(week, @week_of_month-1,  @derived_date))
    select @year, @month, @day_of_week, @week_of_month, @derived_date
    
    /* Test */
    declare @date datetime
    
    set @date = '04-MAY-2009'
    select @date, cast(datename(week,@date) as int)- cast( datename(week,dateadd(dd,1-day(@date),@date)) as int)+1 week_of_month, datepart(dw, @date) day_of_weekhere
    

    【讨论】:

    • -1 跑了这篇文章,它给出了很多行,没有一个看起来像一个合理的答案(除了硬编码的 4-may。)
    • 我的系统设置为英国日期的 dateformat dmy。我已编辑代码以反映这一点 - 请重试
    • 谢谢,这将教会我正确地测试我的代码。我一直忘记不是每个人都是英国人:)
    • select @year = datepart(year, getdate()), @day_of_week = 6, @week_of_month = 5, @month = 6 这进入七月.. 第 5 周必须是最后一周六月..应该是六月 26 日.. 如果月份与传入的月份不同,我可以检查并删除 1 周 if (datepart(month, @derived_date) @month) set @derived_date = dateadd(week, -1,@derived_date)
    【解决方案4】:

    EDIT - 修改为处理@@datefirst的不同值

    我的猜测基于目前可用的数据。

    如果您的 SQL Server 安装将 @@datefirst 设置为星期日 (7) 或星期一 (1),这将起作用。

    测试数据设置为返回 01-May-2009

    declare @dayofweek int
    declare @weekofmonth int
    declare @month int
    declare @datefirst_adjustment int
    
    
    select @datefirst_adjustment = case @@datefirst when 1 then 0
                                                    when 7 then 1
                                   end
    
    declare @firstofyear datetime
    
    set @firstofyear = '20090101'
    
    set @dayofweek = 5
    
    set @month = 5
    
    set @weekofmonth = 1
    
    
    select dateadd(ww,@weekofmonth - 1,dateadd(mm,@month - 1,@firstofyear)) - datepart(dw,dateadd(mm,@month - 1,@firstofyear)) + @dayofweek + @datefirst_adjustment
    

    【讨论】:

    • dayofweek=1, weekofmonth=1, month=5 给出 4 月 26 日,即星期日?
    • 我的@@datefirst 值错误。编辑描述以反映这一点。
    • 在 2009 年 4 月试试这个,weekofmonth = 5 应该是 4 月 26 日(第 5 周 = 一个月的最后一周)??你得到了什么?
    • 第 4 个月第 5 周第 1 天我得到了 4 月 26 日。 select @@datefirst 的值是多少?
    • 嘿.. 选择 @@datefirst 给我 7
    猜你喜欢
    • 2015-04-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 2011-06-06
    • 2018-06-07
    • 1970-01-01
    • 2014-07-01
    相关资源
    最近更新 更多