sql server 2005 convert time to minutes [duplicate] - sql-server

This question already has answers here:
datetime to totalminute in sql
(3 answers)
Closed 7 years ago.
I have a few date time functions within my database, but I need to add one that takes the time portion of a datetime field and then converts the time into minutes
I have a function that get the minutes between two times, but not just the minutes of a single time.
ALTER FUNCTION [dbo].[fn_MinutesBetween]
( #fStart datetime, #fEnd datetime )
RETURNS int
AS
BEGIN
RETURN DateDiff(minute, #fStart, #fEnd)
and another one that gets just the time portion
ALTER function [dbo].[fn_ReturnTimeOnly]
(#DateTime smallDateTime)
returns nvarchar(50)
as
begin
Return substring(cast(#DateTime as varchar),12,len(#DateTime))
end
How can I just get the minutes of the time. Like 1:00 am would be 60, 2:00 am would be 120
12:00 pm would be 720 etc.
Thanks

I was given a link in comments to datetime to totalminute
and used that to come up with a solution.
ALTER FUNCTION [dbo].[fn_ReturnMinutesOnly]
( #dt smalldatetime )
RETURNS int
AS
BEGIN
RETURN DATEDIFF(MINUTE, DATEADD(DAY, DATEDIFF(DAY, 0, #dt), 0), #dt)
END

Get the number of hours, cast to int, multiply by 60, get the number of mins, cast to int, add these two.
ALTER function [dbo].[fn_ReturnMinutesOnly]
(#DateTime smallDateTime)
returns INT
as
begin
Return
cast(substring(cast(#DateTime as varchar),13,2) as INT) * 60 +
cast(substring(cast(#DateTime as varchar),16,2) as INT)
end

Casting to string is expensive (I talk about the opposite scenario here, but the concept is the same). Try this instead:
DECLARE #DateTime DATETIME;
SET #DateTime = GETDATE();
SELECT DATEDIFF(MINUTE, DATEDIFF(DAY, 0, #DateTime), #DateTime);
In your function, this would be:
ALTER function [dbo].[fn_ReturnTimeOnly]
(#DateTime smallDateTime)
returns INT
as
begin
Return (SELECT DATEDIFF(MINUTE, DATEDIFF(DAY, 0, #DateTime), #DateTime));
end

Related

How to get the start and end of a day in T-SQL when daylight savings is enabled?

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

Convert epoch to datetime

On a table I have a bigint column that stores a timestamp with a microsecond precision like:
636453251396217655
636453251398405201
636453251592389899
636453251668326820
I have to build a script that, if that date is older than a week, the row must moved to another table.
I tried to convert to date using:
CREATE FUNCTION [dbo].[UNIXToDateTime] (#timestamp bigint)
RETURNS datetime
AS
BEGIN
DECLARE #ret datetime
SELECT #ret = DATEADD(second, #timestamp, '1970/01/01 00:00:00')
RETURN #ret
END
and used like:
select dbo.UNIXToDateTime(636453251396217655)
but because of the bigint my script crash because:
Arithmetic overflow error during expression conversion in int data
type
I can lose precision, the important is the date part that is the main part of the sql filter.
Demo: http://sqlfiddle.com/#!6/24f05/1
There's an answer here for converting with epoch values:
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (#Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #Days AS INT, #MilliSeconds AS INT
SET #Days = #Epoch / (1000*60*60*24)
SET #MilliSeconds = #Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, #MilliSeconds, DATEADD(DAY, #Days, '1/1/1970')))
END;
You can use that function but simply divide your epoch values. As you are fine with the loss of fidelity, this will suit your needs perfectly. For example:
DECLARE #epoch BIGINT = 636453251396217655
SELECT dbo.[fn_EpochToDatetime](#epoch/100000)

Creating and executing the function in SQL Server

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.

Convert Epoch to DateTime SQL Server (Exceeds Year 2038)

How to convert Epoch to DateTime SQL Server if epoch exceeds the year 2038?
Answer in Convert Epoch to DateTime SQL Server will not work.
Example:
SELECT DATEADD(ss, 2713795200000 / 1000, '19700101')
Thu, 30 Dec 2055 16:00:00 GMT
DATEADD function assumes an INT as an increment to your date, to bypass the limitation of INT you can either reduce the precision of your epoch, or do a slightly complex code to retain the precision of your epoch.
This reduces the precision to minutes:
SELECT DATEADD(MINUTE,#YourEpoch/60/1000, '1/1/1970')
This one splits your epoch to days and milliseconds and then combines them in a datetime
CREATE FUNCTION [dbo].[fn_EpochToDatetime] (#Epoch BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #Days AS INT, #MilliSeconds AS INT
SET #Days = #Epoch / (1000*60*60*24)
SET #MilliSeconds = #Epoch % (1000*60*60*24)
RETURN (SELECT DATEADD(MILLISECOND, #MilliSeconds, DATEADD(DAY, #Days, '1/1/1970')))
END;
However, I'm not quite sure why the 2nd solution is not as precise as I expect it to be.
Building on the response above, the solution provided works but does not protect from trying to convert to a date that is out of bounds for SQL server.
create function dbo.unixTimestampConversion (
#unixTime bigInt
)
returns dateTime2(7)
as
begin
declare
#output dateTime2(7)
, #days int
, #ms int
, #x int = (1000 * 60 * 60 * 24)
;
set #days = #unixTime / #x
;
set #ms = #unixTime % #x
;
if (#unixTime < 32503593600000 and #unixTime > -2208988800000)
begin
set #output = dateAdd (millisecond, #ms, dateAdd (day, #days, '1/1/1970'))
;
end
;
else if (#unixTime <= -2208988800000)
begin
set #output = '1/1/1900'
;
end
;
else if (#unixTime >= 32503593600000)
begin
set #output = '12/31/2999'
;
end
;
return #output
;
end
;
You can assign the epoch time to your datetime directly (I tried this on SQL Server 15.0). Although it considers the number as the number of days since 1900-1-1 00:00:00 so you have to add 2208988800 (the number of seconds in 70 years) and then divide by 86400(number of seconds in a day).
DECLARE #time DATETIME = (2208988800.0 + [your epoch time in seconds])/86400;
However, it seems to be 0.007s or 0.003s behind the given epoch. Also, I'm not sure if this is faster than the DATEADD() function.
create a function to convert epoch to datetime and use them in your query like
below
create FUNCTION [dbo].[from_unixtime] (#Datetime BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #LocalTimeOffset BIGINT
,#AdjustedLocalDatetime BIGINT;
SET #LocalTimeOffset = DATEDIFF(second,GETDATE(),GETUTCDATE())
SET #AdjustedLocalDatetime = #Datetime - #LocalTimeOffset
RETURN (SELECT DATEADD(second,#AdjustedLocalDatetime, CAST('1970-01-01 00:00:00' AS datetime)))
END;
and then use this function in your query

Compare SQL server datetime column to year month?

SELECT * FROM TABLE
WHERE YEAR(MDTFlgtStart)=YEAR(GETDATE()) AND MONTH(MDTFlgtStart)=MONTH(GETDATE())
Above code it compares with present year and month with the column year and month.
But do we have any chance we can give year=2012 month =3
or year =2011 month=5
You could declare variables:
DECLARE #YEAR AS INT
DECLARE #MONTH AS INT
SET #YEAR = 2012
SET #MONTH = 3
SELECT *
FROM TABLE
WHERE YEAR(MDTFlgtStart)=#YEAR AND MONTH(MDTFlgtStart)=#MONTH
You can wrap the above in a procedure for re-usability....
You can just use parameters for those values. As a bonus, avoiding functions against the column will help assist a seek if an index exists on the column (of course SELECT * means it will likely end up as a full scan anyway, or a range scan and a bunch of lookups)...
-- these would be input parameters for your stored procedure
DECLARE #y INT = 2011, #m INT = 5;
-- now have a date variable:
DECLARE #dt DATE = DATEADD(MONTH, #m-1, DATEADD(YEAR, #y-1900, 0));
SELECT ... FROM dbo.tablename
WHERE MDTFlgtStart >= #dt
AND MDTFlgtStart < DATEADD(MONTH, 1, #dt);
Also you should stop inviting whoever named these columns to lunch, because I have to assume they're not very nice.

Resources