String to time in SQL Server 2008 - sql-server

I have searched on this but my string seems to be in a different format to the examples I can find.
I have a time set as a nvarchar(50) and values such as 1535
I have two of these columns and I want to compare the two to find how many minutes difference there is. How do I convert the string to a time?

One way;
declare #t1 nvarchar(4) = '1535'
declare #t2 nvarchar(4) = '1700'
select
datediff(minute,
cast(stuff(#t1, 3, 0, ':') as time),
cast(stuff(#t2, 3, 0, ':') as time))
>>85

If you need the difference in minutes, this is a method without converting your values to Datetime.
Assuming all nvarchar values are convertible to int and they are in 24h format, difference of c2-c1 in Minutes:
Fiddle demo here
select ((c2*1-c1*1)/100)*60 + (c2*1-c1*1)%100 inMinutes
from t

Assuming all your values can be convertible to Time:
DECLARE #val1 as NVARCHAR(50);
DECLARE #val2 as NVARCHAR(50);
SET #val1 = '1535'; SET #val2 = '1655';
SELECT DATEDIFF(minute,convert(time,LEFT(#val1,2)+':'+RIGHT(#val1, 2)+':00'), CONVERT(time,LEFT(#val2,2)+':'+RIGHT(#val2, 2)+':00'))

Related

Cast '2016-07-2914:50:13.75300' varchar to datetime T-SQL

I have varchar '2016-07-2914:50:13.75300' and want to convert it to datetime data type.
I tried with select cast('2016-07-2914:50:13.75300' as datetime)
but I am getting
Conversion failed when converting date and/or time from character string.
Insert a space between DDHH and lose the last two MS digits:
select cast(left(stuff('2016-07-2914:50:13.75300', 11, 0, ' '), 23) as datetime)
why don't you simply use
select stuff('2016-07-2914:50:13.75300', 11, 0, ' ') ?
Different approach using SUBSTRING, of course STUFF is the way to go.
DECLARE #TIME VARCHAR(50) = '2016-07-2914:50:13.75300'
SELECT CAST(SUBSTRING(#TIME, 1, 10) AS DATETIME) +
CAST(SUBSTRING(#TIME, 11, LEN(#TIME) - 10) AS TIME)
Result:
2016-07-29 14:50:13.753

Random Datetime In given Datetime Range

I need to get a random date-time within a range of 2 date-times in T-SQL for MS-SQL server 2012. It is necessary for me that it goes to the precision of seconds, I need DATETIME2(0) as datatype for both input and output. I have done some research online but the answers I could find are either for dates only or are for other database types.
The code should do something like:
Input: ('2015-01-01 08:22:13' , '2015-03-05 17:56:31') <-- I will use a select statement to replace these absolute numbers
Return: ('2015-02-11 14:32:45') <--this should be randomized
Can anyone help me out with this?
Thanks in advance
One option is to randomize the numbers of seconds between FromDate and ToDate, and then add it to FromDate. Hope it works for you.
DECLARE #FromDate DATETIME2(0)
DECLARE #ToDate DATETIME2(0)
SET #FromDate = '2015-01-01 08:22:13'
SET #ToDate = '2015-03-05 17:56:31'
DECLARE #Seconds INT = DATEDIFF(SECOND, #FromDate, #ToDate)
DECLARE #Random INT = ROUND(((#Seconds-1) * RAND()), 0)
SELECT DATEADD(SECOND, #Random, #FromDate)

Extract a number after a number pattern in SQL

I am working in SQL server. I have some number like 130-0029. I need to get the integer after the - delimiter out of it. So in this example I need to return 29. These are the following scenarios I have with this,
The pattern may differ like 130-00000029 or 130-0029.
If there are all 0's then print 0, else get actual number like 29.
Please advise/suggest me on this.
Here is an example:
declare #s varchar(100) = '130-0029'
select cast(substring(#s, patindex('%[-]%', #s) + 1, len(#s)) as int)
You may need to cast to some numeric if the number overflows ineteger type.
Try this:
DECLARE #num varchar(50) = '130-0029'
SELECT CAST(SUBSTRING(#num, CHARINDEX('-', #num) + 1, LEN(#num)) AS INT)
Here is a fiddle.
This also works if the - is missing. But if what follows is not a number it will give an error.
declare #string as varchar(100)
set #string = '130-0029'
select convert(int,Right(#string, LEN(#string)-CHARINDEX('-', #string)))
Probably not so different than other answers, but this works using STUFF too:
DECLARE #String VARCHAR(10) = '130-0029';
SELECT CONVERT(INT, STUFF(#String, 1, CHARINDEX('-', #String), ''));
See this running in Query Stack Exchange.

Convert UTC Milliseconds to DATETIME in SQL server

I want to convert UTC milliseconds to DateTime in SQL server.
This can easily be done in C# by following code:
DateTime startDate = new DateTime(1970, 1, 1).AddMilliseconds(1348203320000);
I need to do this in SQL server. I found some script here, but this was taking initial ticks from 1900-01-01.
I have used the DATEADD function as below, but this was giving an arithmetic overflow exception by supping milliseconds as difference:
SELECT DATEADD(MILLISECOND,1348203320000,'1970-1-1')
How can I do the conversion properly?
DECLARE #UTC BIGINT
SET #UTC = 1348203320997
SELECT DATEADD(MILLISECOND, #UTC % 1000, DATEADD(SECOND, #UTC / 1000, '19700101'))
Below the function that converts milliseconds to datetime
IF object_id('dbo.toDbTimeMSC', 'FN') IS NOT NULL DROP FUNCTION dbo.toDbTimeMSC
GO
CREATE FUNCTION [dbo].[toDbTimeMSC] (#unixTimeMSC BIGINT) RETURNS DATETIME
BEGIN
RETURN DATEADD(MILLISECOND, #unixTimeMSC % 1000, DATEADD(SECOND, #unixTimeMSC / 1000, '19700101'))
END
GO
-- select dbo.toDbTimeMSC(1348203320000)
I had problems with using answers given here (especially that the system was counting ticks form 0001-01-01) - so I did this:
CONVERT(DATETIME,[Time]/ 10000.0/1000/86400-693595)
--explanation for [Time_in_Ticks]/ 10000.0/1000/86400-693595
--Time is in "ticks"
--10000 = number of ticks in Milisecond
--1000 = number of milisecons in second
--86400 = number of seconds in a day (24hours*60minutes*60second)
--693595= number of days between 0001-01-01 and 1900-01-01 (which is base
-- date when converting from int to datetime)
Using SQL Server 2008R2 this produced the required result:
CAST(SWITCHOFFSET(CAST(dateadd(s, convert(bigint, [t_stamp]) / 1000, convert(datetime, '1-1-1970 00:00:00')) AS DATETIMEOFFSET), DATENAME (TZoffset, SYSDATETIMEOFFSET())) AS DATETIME)
The DATEADD requires an integer as a second argument. Your number 1348203320000 is very large for integer therefore it produce an error in runtime. Your should use bigint type instead and provide DATEADD with correct int values by splitting your milliseconds to seconds and milliseconds. That is sample you could use.
DECLARE #total bigint = 1348203320000;
DECLARE #seconds int = #total / 1000
DECLARE #milliseconds int = #total % 1000;
DECLARE #result datetime = '1970-1-1';
SET #result = DATEADD(SECOND, #seconds,#result);
SET #result = DATEADD(MILLISECOND, #milliseconds,#result);
SELECT #result
Right now, you can use dateadd with division on minutes and not seconds.
The code will be like this:
DATEADD(MILLISECOND, epoch% 60000, DATEADD(MINUTE, epoch/ 60000, '19700101'));
=dateadd("d",INT((Fields!lastLogon.Value / 864000000000)- 134774),"1970-01-01 00:00:00")
That's what I used in SSRS to get around the INT error, use days instead of seconds. Is it wrong?

SQL convert int to time

I have a database that displays time as an integer. However I am wanting to output this into a report with the correct format. This is the format that I would like to change:
eg.
183000 would become 18:30
500 would become 00:05
160000 would become 16:00
and so on.
I have had a look and CAST and CONVERT but not successfully managed to get this the time in the correct format.
Assuming your input will always be an int, you can parse it with something like:
DECLARE #stringTime varchar(6)
SET #stringTime = RIGHT('000000' + CAST(intTime AS VARCHAR), 6)
SELECT CAST(LEFT(#stringTime, 2) + ':' + RIGHT(LEFT(#stringTime, 4), 2) AS TIME) as TimeValue
I'd DEFINITELY look to change this field to an actual time or datetime field, as this level of conversion is not advised, especially for a heavily used database. There's just really got to be a better way to store your data.
Using an int value this way allows for a lot of bad data, without adding a lot of additional checks and/or constraints on your inputs (i.e.: 260000, 127900, etc.)
looks like you need to divide by 100 to get the seconds, divide by 10000 to get the minutes, and divide by 1000000 to get the hours, then format those values as a string, inserting a colon between hours and minutes, like
hh:mm
First cast to a varchar field and convert all times to 4 digits adding leading zeros if need be (500 would become 0500)and then break up the field with concantenation Left(myfield,2) + ':' + right(myfield,2)
This is something stupid to do every time you run a report, it is wasteful of server resources. If possible change the field to varchar and runthe code once. If not possible, can you add a formatted field and have a trigger do the formatiing on insertion (you'll still need to update the field the first time? Possibly a constraint would do instead of a trigger, but that would depend on the database.
I'm assuming that you are on SQL Server based on use of CONVERT and your previous questions.
You could use DATEADD for this too.
WITH Times AS
(
SELECT 183000 AS T
UNION ALL
SELECT 500
UNION ALL
SELECT 160000
)
SELECT CAST(DATEADD(SECOND, T%100 + (60*(T%10000 / 100)) + 3600*(T/10000),0)
AS time /*Or datetime if < SQL Server 2008*/)
FROM Times
declare #i int = 235959
select cast(stuff(stuff(
case when len(cast(#i as varchar(6))) = 6 then cast(#i as varchar(6))
else REPLICATE('0',6 - LEN(cast(#i as varchar(6))))+cast(#i as varchar(6))
end
,3,0,':'), 6, 0,':') as datetime)
set #i = 500
select cast(stuff(stuff(
case when len(cast(#i as varchar(6))) = 6 then cast(#i as varchar(6))
else REPLICATE('0',6 - LEN(cast(#i as varchar(6))))+cast(#i as varchar(6))
end
,3,0,':'), 6, 0,':') as datetime)
DECLARE #intTime int
SET #intTime = 50000
SELECT CAST(STUFF(STUFF(CONCAT(REPLICATE('0', 6 - LEN(#intTime)),#intTime),3,0,':'),6,0,':') AS TIME(0))
ALTER FUNCTION [dbo].[MinutesToDuration]
(
#minutes int
)
RETURNS nvarchar(30)
AS
BEGIN
declare #hours nvarchar(20)
DECLARE #XX NVARCHAR(10)
DECLARE #HH VARCHAR(2)
DECLARE #TT VARCHAR(2)
DECLARE #BL NVARCHAR(2)
DECLARE #TM VARCHAR(5)
SET #XX=#minutes
IF #XX<60
BEGIN
IF #XX<10
BEGIN
SET #HH='00'
SET #TT='0'+#XX
END
ELSE
BEGIN
SET #HH='00'
SET #TT=#XX
END
END
ELSE
BEGIN
IF #XX%60=0
BEGIN
SET #HH=#XX/60
SET #TT='00'
END
ELSE
BEGIN
SET #BL= #XX%60
IF #BL<10
BEGIN
SET #HH=#XX/60
SET #TT='0'+#BL
END
ELSE
BEGIN
SET #HH=#XX/60
SET #TT=#BL
END
END
END
SET #hours= #HH+':'+#TT
return #hours
END

Resources