I have a week of month in sql and i need to generate a datetime varible from that.. fields i have are dayofweek, weekofmonth and month values. anyone know of a quick effective way to calculate this in mssql 2005? Thanks
Keep in mind. if week of month is set to 5 it is the last week of the month
Examples are i have DayOfWeek, month, year, weekofmonth..
so lets say i have DayOfWeek = 2 (monday)
month = 5 ( may)
year = 2009
weekofmonth = 5
i would expect monday may 25th 2009
DayOfWeek = 1, Month = 5, Week = 1, year = 2009 = Sunday, May 3rd 2009
DayOfWeek = 5, Month = 4, Week = 3, Year = 2009 = Thursday, April 16th 2009
Additional Info:
I am using the .net TimezoneInfo.TransitionTime class library to help me store some stuff in the db.. they say:
The Month property defines the month in which the time change occurs. The Day property defines the day of the week on which the transition occurs. The Week property determines which week of the month the time change occurs in. Valid values of the Week property can range from 1 to 5. A value of 5 indicates the last week of the month.
so far i have this:
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
anything cleaner?
This is fairly simple, and really just adds days and weeks to the first day of that month. It assumes you're using the current year, and won't really handle things like the 5th week of February. (Example: 5th week, 3rd day of February gives 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'))
It also assumes that DayOfWeek == 1 for the first day of the month, so it's almost definitely wrong. Can we see some sample data and expected outputs?
The first week of May starts on Friday. So what date would be dayofweek=1, weekofmonth=1, month=5? Is that Monday April 27th?
/*
* 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
EDIT - amended to handle different values of ##datefirst
My guess based on the data available so far.
This will work if you SQL server installation has ##datefirst set to Sunday(7) or Monday(1).
The test data is set up to return 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
Related
I'm not sure if I get this right. Please someone explain to me. I don't know what deatiles should I add to shis function. I gues somwone who knows sql well will know this easily
declare #date datetime = '2016-05-01',
#ndays INT = 11,
#country NVARCHAR(2)
BEGIN
IF #date IS NULL
BEGIN
SET #date = GETDATE();
END
IF #country IS NULL
BEGIN
SET #country = 'HU';
END
DECLARE #count INT = 1
DECLARE #newdate datetime
DECLARE #firstdayofmonth date = DATEADD(month, DATEDIFF(month, 0, #date), 0)
WHILE DATEPART(weekday,#firstdayofmonth) in (7,1)
BEGIN
SET #firstdayofmonth = DATEADD(DAY, 1, #firstdayofmonth)
END;
SET #newdate = #firstdayofmonth
WHILE #count < #ndays
BEGIN
SET #newdate = DATEADD(DAY, 1, #newdate)
IF (DATEPART(WEEKDAY, #newdate) not in (1,7))
SET #count += 1;
END
select #newdate
END
I get that this is about declaring a date. The firstdayofmonth calculatio is confusing in it.
This is clearly no mysql code weekday goes from 0 to 6. Also you can't declare variables that way.
Also you should have posted the whole code.
AS for your code:
The first While Clause searches for the first Monday in a Month.
The second counts all Working Days (Monday till Friday) of that chosen Month.
With the first variables, you can manipulate which Month, but what that country has to do with it I can only guess that you have a list of all public holiday fur Hungary.
#newdate becomes the first weekday of the month (Monday-Friday). If the month starts on a weekend (Saturday or Sunday), it shifts up until Monday; otherwise it stays the same. As for the second part, #count looks like it ends up being the number of weekdays in the first eleven days since the start of the first weekday.
I am currently working on a SQL Server script where we collect aggregated data on a daily basis for last 'n' days. In order to do this, we create a temp table with the start time and end time for all days for the last 'n' days. The code is as below.
DECLARE #Tbl TABLE (Begin DATETIME, End DATETIME)
DECLARE #i INT = 1
DECLARE #begin DATETIME = DATEADD(DD, DATEDIFF(DD, 1, GETDATE()), 0)
DECLARE #end DATETIME = DATEADD(DD, 1, #begin)
WHILE #i <= #n
INSERT INTO #Tbl
SELECT #begin, #end
SET #end = #begin
SET #begin = DATEADD(DAY, -1, #end)
SET #i = #i + 1
END
We convert these dates to UTC by calling an inbuilt function which does the operation correctly as expected but throws an error for November 4th 2018 00:00:00 as this is not a valid local time.
The issue with the above code is that it generates the date with the 0th hour of begin date and 0th hour of end date. Although some of these dates might be impractical due to daylight savings.
For example, if you consider the Brazil timezone, daylight saving was enabled on November 4th at 00:00:00 to 01:00:00 which makes the date 2018-11-04 00:00:00 incorrect to be converted to UTC.
Is there any known functions which can be used to pass a date and get the valid start time for the day and valid end time for the day in local time?
For local time start date and end date please use following code
DECLARE #startDate DATETIME, #endDate DATETIME
SET #startDate=DATEFROMPARTS(YEAR(getdate()),MONTH(getdate()),DAY(getdate()))
SET #endDate=getdate()
SELECT #startDate,#endDate
For UTC time please replace getdate() function with getutcdate() in above code
GETUTCDATE()
Returns the UTC Date and Time
In a conditional I would like to check if current day is Sunday independently of the local setting so I have done:
DECLARE #IsSunday BIT
SELECT
#IsSunday = CASE
WHEN DATEPART(DW, getdate() + ##DATEFIRST - 1) = 7
THEN 1
ELSE 0
END
IF #IsSunday
BEGIN
// Do some stuff
END
I need someone to confirm me that this will work under any local setting, for example, SQL Servers with English configuration and other languages.
In Spanish configuration above code is working.
Pick any Sunday, for example 20170910, and calculate the difference in days between that Sunday and the date you need to check.
If the result of modulo 7 is 0 you have a Sunday.
select case when datediff(day, '20170910', getdate()) % 7 = 0
then 1
else 0
end;
You can use the DateName function in sql server. For more detail please refer the below query.
DECLARE #IsSunday BIT
SELECT #IsSunday = CASE WHEN UPPER(DATENAME(DW, getdate())) = 'SUNDAY' THEN 1 ELSE 0 END
IF #IsSunday
BEGIN
// Do some stuff
END
Here is one way to do it:
DECLARE #DATEFIRST int = ##DATEFIRST; -- Get the current first day of the week
SET DATEFIRST 7; -- Set the first day of the week to sunday (U.S default)
SELECT CASE WHEN DATEPART(WEEKDAY, GETDATE()) = 1 THEN -- If the weekday is 1 it's Sunday
1
ELSE
0
END As IsSunday;
SET DATEFIRST #DATEFIRST; -- set the first day of the week to back it's original value
Of course, If you don't want to set the datefirst back to it's original value, you can simply set it to 7 and remove the first and last rows of the code.
Also, I've tested your original code and it seems to be working fine:
DECLARE #i int = 1
WHILE #i < 8
BEGIN
SET DATEFIRST #i;
SELECT CASE WHEN (DATEPART(WEEKDAY, '2017-08-27') + ##DATEFIRST - 1) = 7 THEN 1 ELSE 0 END
SET #i = #i + 1
END
Returns 1 every time.
compare the daynumber of your date with the day of a known sunday
declare #IsSunday bit
Declare #yourdate date = '20170820'
select #IsSunday = case when datepart(dw, '20170827') = datepart(dw, #yourdate)
then 1 -- sunday
else 0 -- not sunday
end
IF #IsSunday
BEGIN
-- Do some stuff
END
where '20170827' is a known sunday and is a constant which you should not change
Im trying to complete this function that will take an input date and return a date that is a Sunday 3 weeks ago.
For example: If my input date is 5/25/2016, then the result should be 5/1/2016
I have put together most of the function, just stumped as to what to do next.
IF OBJECT_ID (N'dbo.ufnSundayThreeWeeksBack', N'FN') IS NOT NULL
DROP FUNCTION ufnSundayThreeWeeksBack;
GO
CREATE FUNCTION dbo.ufnSundayThreeWeeksBack(#SOMEDATE datetime)
RETURNS date
AS
BEGIN
IF #SOMEDATE IS NULL
RETURN NULL;
DECLARE #result date;
SELECT #result = DATEADD(WEEK, -7, DATEADD(DAY, 1 - DATEPART(WEEKDAY, #SOMEDATE), #SOMEDATE))
RETURN #result;
END;
GO
Try this:
IF OBJECT_ID(N'dbo.ufnSundayThreeWeeksBack', N'FN') IS NOT NULL
DROP FUNCTION ufnSundayThreeWeeksBack;
GO
CREATE FUNCTION dbo.ufnSundayThreeWeeksBack ( #SOMEDATE DATETIME )
RETURNS DATE
AS
BEGIN
DECLARE #DateMinus3Weeks DATE = DATEADD(WEEK, -3, #SOMEDATE);
RETURN DATEADD(DAY, -(DATEPART(WEEKDAY, #DateMinus3Weeks)-1), #DateMinus3Weeks);
END;
GO
Basically subtracting 3 weeks from the given date and then subtracting the weekdaynumber to get to the sunday.
In a scenario, I have to check whether daylight savings is in effect or not. Based on the outcome of the check, I have to do some calculations in a SQL server procedure.
What is the best way to quickly check if daylight savings is currently in effect?
I used this Daylight Savings Time Functions in SQL Server that is created by Tim Cullen.
Specifically, the code that I used was:
Start Date Function
CREATE function [dbo].[fn_GetDaylightSavingsTimeStart]
(#Year varchar(4))
RETURNS smalldatetime
as
begin
declare #DTSStartWeek smalldatetime, #DTSEndWeek smalldatetime
set #DTSStartWeek = '03/01/' + convert(varchar,#Year)
return case datepart(dw,#DTSStartWeek)
when 1 then
dateadd(hour,170,#DTSStartWeek)
when 2 then
dateadd(hour,314,#DTSStartWeek)
when 3 then
dateadd(hour,290,#DTSStartWeek)
when 4 then
dateadd(hour,266,#DTSStartWeek)
when 5 then
dateadd(hour,242,#DTSStartWeek)
when 6 then
dateadd(hour,218,#DTSStartWeek)
when 7 then
dateadd(hour,194,#DTSStartWeek)
end
end
End Date Function
CREATE function [dbo].[fn_GetDaylightSavingsTimeEnd]
(#Year varchar(4))
RETURNS smalldatetime
as
begin
declare #DTSEndWeek smalldatetime
set #DTSEndWeek = '11/01/' + convert(varchar,#Year)
return case datepart(dw,dateadd(week,1,#DTSEndWeek))
when 1 then
dateadd(hour,2,#DTSEndWeek)
when 2 then
dateadd(hour,146,#DTSEndWeek)
when 3 then
dateadd(hour,122,#DTSEndWeek)
when 4 then
dateadd(hour,98,#DTSEndWeek)
when 5 then
dateadd(hour,74,#DTSEndWeek)
when 6 then
dateadd(hour,50,#DTSEndWeek)
when 7 then
dateadd(hour,26,#DTSEndWeek)
end
end
I then use the functions like this in my query:
declare #DLSStart smalldatetime
, #DLSEnd smalldatetime
, #DLSActive tinyint
set #DLSStart = (select MSSQLTIPS.dbo.fn_GetDaylightSavingsTimeStart(convert(varchar,datepart(year,getdate()))))
set #DLSEnd = (select MSSQLTIPS.dbo.fn_GetDaylightSavingsTimeEnd(convert(varchar,datepart(year,getdate()))))
if #Date between #DLSStart and #DLSEnd
begin
set #DLSActive = 1
end
else
begin
set #DLSActive = 0
end
select #DLSActive
In Western Europe, the summer time starts the last Sunday of March at 02:00
select
DATEADD(
day,
DATEDIFF(
day,
'1900-01-07',
DATEADD(month,DATEDIFF(MONTH,0,concat(year(getdate()),'-03-01')),30)
)/7*7,
'1900-01-07 02:00'
) as SummerTimeStarts
and ends the last Sunday of October at 03:00
Select
DATEADD(
day,
DATEDIFF(
day,
'1900-01-07',
DATEADD(month,DATEDIFF(MONTH,0,concat(year(getdate()),'-10-01')),30)
)/7*7,
'1900-01-07 03:00'
) as SummerTimeEnds
It gives as en function :
CREATE function [dbo].[DateIsSummerTime]
(#datetime datetime)
RETURNS bit
as
begin
declare #SummerTimeStarts datetime, #SummerTimeEnds datetime
set #SummerTimeStarts = (select DATEADD(day,DATEDIFF(day,'1900-01-07',DATEADD(month,DATEDIFF(MONTH,0,concat(year(getdate()),'-03-01')),30))/7*7,'1900-01-07 02:00'))
set #SummerTimeEnds = (Select DATEADD(day,DATEDIFF(day,'1900-01-07',DATEADD(month,DATEDIFF(MONTH,0,concat(year(getdate()),'-10-01')),30))/7*7,'1900-01-07 03:00'))
Return Case when #datetime > #SummerTimeStarts and #datetime < #SummerTimeEnds then 1 else 0 end
end