I wrote a stored procedure who take a reference date, and add a hour to this element.
Here is my line doing the operation :
DATEADD(day, DATEDIFF(DAY, 0, #conductor_date), [HOUR])
For example, whith #conductor_date = '2015-10-15' and [HOUR] = 23:00 it works and generate me a date like that : '2015-10-15:23:00:00'
I face a logical issue when the value [HOUR] is more than 24. In fact, to solve my problem I need to generate '2015-10-16:00:40:00' when [HOUR] = 24:40
Actualy with this values, I face the logical following exception :
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
To sum up, I need to take care of hours that are more than '23:59' and switch to the next day :
DECLARE #conductor_date datetime
DECLARE #hour varchar(5)
SET #conductor_date = '2015-10-15'
SET #hour = '24:40'
SELECT DATEADD(day, DATEDIFF(DAY, 0, #conductor_date), #hour)
Expected : 2015-10-16:00:40:00
According to the documentation, date / time types don't support times larger then 23:59:59.9999999. You have to do manual string parsing for this.
First you need to extract the total hours, divide that by 24 to get total days. Then calculate leftover hours, and with that reconstruct your time offset.
With these in hand, you can build your required output value:
DECLARE #v VARCHAR(20) = '24:40'
DECLARE #start VARCHAR(20) = '2015-10-15'
DECLARE #days INT
DECLARE #leftover INT
SET #leftover = CAST(LEFT(#v, 2) AS INT)
SET #days = #leftover / 24
SET #leftover = #leftover - #days * 24
SET #v = CAST(#leftover AS VARCHAR(2)) + SUBSTRING(#v, 3, 20)
SELECT DATEADD(DAY, #days + DATEDIFF(DAY, 0, #start), #v)
Here's a working SQLFiddle.
This supports time string that start with HH (leading zeros) with any valid accuracy (HH:mm:ss.fffffff).
You can split your #hour field into hours and minutes and add them separately:
DECLARE #conductor_date datetime
DECLARE #hour varchar(5)
DECLARE #hours int
DECLARE #minutes int
DECLARE #offset datetime
SET #conductor_date = '2015-10-15'
SET #hour = '24:40'
SET #hours = cast(left(#hour, 2) as int)
SET #minutes = cast(right(#hour, 2) as int)
SET #offset = dateadd(day, datediff(day, 0,#conductor_date), 0) -- the begin of the day
SELECT DATEADD(hour, #hours, dateadd(minute, #minutes, #offset))
Of course all can be done in one line but for sake of visualization I have put it into separate statements.
You may try below query
SELECT DATEADD(MINUTE,(LEFT(#hour,2)*60+RIGHT(#hour,2)),#conductor_date)
Related
I have a string which contains a duration in minutes and seconds, as '1302:47'.
I want to store this in SQL Server and I chose the time data type.
How do I convert '1302:47' in to hrs:mins:secs to a time datatype?
I tried
SELECT TRY_PARSE('1302:40' AS time)
SELECT TRY_CONVERT(time, '1302:40')
and end up with NULL both times implying the conversion failed.
I am expecting 21:7:40 as in 21hrs, 7mins and 40seconds.
Should I use a different data type?
Should I convert it all to seconds and just store as an int?
You need to split your string by ':' char, since that time in invalid. That's why you're getting a NULL value.
After that, you can try parse both the minutes and the seconds.
Finally, just add the minutes and seconds into a new empty time.
Example supporting the max of 23h:
DECLARE #date VARCHAR(20) = '1302:40';
DECLARE #min INT = ISNULL(TRY_PARSE(LEFT(#date,CHARINDEX(':',#date)-1) AS INT), 0);
DECLARE #sec INT = ISNULL(TRY_PARSE(RIGHT(#date,LEN(#date)-CHARINDEX(':',#date)) AS INT), 0);
DECLARE #time TIME = '00:00'
PRINT DATEADD(s, #sec, DATEADD(mi, #min, #time));
-- Outputs: 21:42:40.0000000
Example supporting more than 23h:
DECLARE #date VARCHAR(20) = '1302:47';
--DECLARE #date VARCHAR(20) = '3600:60';
DECLARE #min INT = ISNULL(TRY_PARSE(LEFT(#date,CHARINDEX(':',#date)-1) AS INT), 0);
DECLARE #sec INT = ISNULL(TRY_PARSE(RIGHT(#date,LEN(#date)-CHARINDEX(':',#date)) AS INT), 0);
DECLARE #time TIME = '0001-1-1 00:00'
IF #min < 1440
BEGIN
PRINT CAST(DATEADD(s, #sec, DATEADD(mi, #min, #time)) AS VARCHAR(8));
END
ELSE
BEGIN
IF #sec = 60
BEGIN
SET #sec = 0;
SET #min = #min +1;
END
PRINT CONCAT(#min/60, ':', FORMAT(#min - (#min/60) * 60,'0#'), ':', FORMAT(#sec,'0#'))
END
-- Scenario #1. Given '1302:47', outputs: 21:42:47
-- Scenario #2. Given '3600:60', outputs: 60:01:00
I have three var char values as
#hour = '18'
#minute = '25'
#seconds = '45'
I need output in the form of '18:25:45'
Select from Convert(Time,#hour+#minute+#seconds)
values in hour minute and seconds coming from SSRS report drop down
You can 'add-up' the values from zero, like this:
declare #hour smallint = 18
declare #minute smallint = 25
declare #seconds smallint = 45
declare #result time
SELECT #result = DATEADD(hour, #hour, DATEADD(minute, #minute, DATEADD(second, #seconds, 0)))
An implicit conversion is not allowed. One solution could be to organise the format as a string and then convert to time as below.
declare #hour smallint = '18'
declare #minute smallint = '25'
declare #seconds smallint = '45'
declare #format varchar(8) = (select (CAST(#hour as varchar(2)) + ':'+ CAST(#minute as varchar(2))+':'+ CAST(#seconds as varchar(2))))
select CAST(#format as time)
Try with this 24-H date format, It will Work.
SELECT CONVERT(VARCHAR(8),GETDATE(),108) AS TimeResult
i need to get the time duration in (hh:mm:ss) format between the two dates
2011/05/05 11:45:02 and 2011/05/01 08:09:57
For example if I had these two dates 2011/05/05 01:18:14 and 2011/05/05 11:00:00, the result would be: 02:18:14
DECLARE #dt1 datetime
DECLARE #dt2 datetime
SELECT #dt1 = '2011-05-05 11:45:02', #dt2 = '2011-05-05 08:09:57'
SELECT CONVERT(VARCHAR(8),#dt1-#dt2,108)
-- RESULT IS : 03:35:05
As far as i know there is no DATETIME_INTERVAL Data type in SQL (or TSQL) , so the only way you have to accomplish this is to manually format the result of a DATEDIFF function.
declare #hours as int
declare #minutes as int
declare #seconds as int
declare #time_interval as nvarchar(10)
set #hours = DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') / 3600
set #minutes = (DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') - #hours*3600)/60
set #seconds = DATEDIFF(ss,'2011/05/05 01:18:14', '2011/05/05 11:00:00') - #hours*3600 - #minutes * 60
set #time_interval = (cast(#hours as nvarchar) +':'+ cast(#minutes as nvarchar)+':'+ cast(#seconds as nvarchar))
print #time_interval
Try this:
declare #date1 datetime='2011/05/05 01:18:14', #date2 datetime='2011/05/05 11:00:00'
select CAST((#date2-#date1) as time(0))
Here is important order of elements in statement.In other case you will get 24h-your time.
How can I get the whole time like this datediff(time, logindate, logoutdate)
I know this built-in function doesn't accept time argument but how can I get the whole time rather than minute, millisecond, second etc. ?
logindate datetime2
logoutdate datetime2
I want something like 1:05:45 rather than portion of it.
Try this
create table dbo.UserLog (UserID VARCHAR(32),loginDate DATETIME,logoutDate DATETIME)
insert into userLog VALUES ('SPARKY','11/14/2009 3:25pm',getDate())
insert into userLog VALUES ('JANNA','11/14/2009 10:45am',getDate())
select UserId,loginDate,logoutDate,
convert(varchar(12),dateAdd(mi,datediff(mi,logindate,logoutdate),'Jan 1 1753 12:00AM'),114) as timeSpent
FROM userLog
Basically, adding the minutes difference between the dates to the earliest valid SQL date and returning the value formatted as a time.
To have difference in days:
select cast(logoutdate - logindate as float) from table_name
or just
select logoutdate - logindatefrom table_name
You can evaluate days, hours, minutes from it.
EDIT
To have it formatted as time:
SELECT CONVERT(VARCHAR,DATA_KOSZTU - DATA_OST_ZMIANY,108) FROM TR_KOSZT
It will work if users are not logged for more than 24 hours, because CONVERT is used to format datetime, not timespan.
Because MSSQL do not have timepsan datatype, datediff returning in absolute integer from milliseconds to years should be enough for you to create a instance of say TimeSpan in .NET.
What Sql Server version are you talking about? In SQL Server 2000 and later, at least,
SELECT datediff(ss,'2006-11-10 05:47:53.497','2006-11-10 05:48:10.420')
will give you the difference between those two datetimes in seconds.
E.g.
select CONVERT(varchar(10),GETDATE(),108)
Here's the solution you are looking for.
DECLARE #Date1 datetime
DECLARE #Date2 datetime
SET #Date2 = '2006-11-15 07:26:25.000'
SET #Date1 = '2009-11-15 05:35:45.000'
-- -----------------------
-- Math done by hand 1:50:40
--
DECLARE #TotalSeconds bigint
DECLARE #Hours bigint
DECLARE #Minutes bigint
DECLARE #Seconds bigint
DECLARE #HH varchar(20)
DECLARE #MM varchar(2)
DECLARE #SS varchar(2)
DECLARE #Result varchar(50)
--
SET #TotalSeconds = datediff(ss,#Date1 ,#Date2)
SET #Hours = FLOOR(#TotalSeconds / 3600)
SET #TotalSeconds = #TotalSeconds % 3600
SET #Minutes = FLOOR(#TotalSeconds / 60)
SET #Seconds = #TotalSeconds % 60
--
SET #HH = CAST(#Hours as varchar)
SET #MM = CAST(#Minutes as varchar)
SET #SS = CAST(#Seconds as varchar)
IF #Minutes < 10 SET #MM = '0' + #MM
IF #Seconds < 10 SET #SS = '0' + #SS
--
SET #Result = #HH + ':' + #MM + ':' + #SS
SELECT #Result
In my table I have a Month(tinyint) and a Day(tinyint) field. I would like to have a function that takes this month and day and produces a datetime for the next date(including year) given this month and day.
So if I had Month = 9, Day = 7 it would produce 9/7/2009.
If I had Month 1, Day 1 it would produce 1/1/2010.
something like this would work. It's variation on your method, but it doesn't use the MM/DD/YYYY literal format, and it won't blowup against bad input (for better or for worse).
declare #month tinyint
declare #day tinyint
set #month = 9
set #day = 1
declare #date datetime
-- this could be inlined if desired
set #date = convert(char(4),year(getdate()))+'0101'
set #date = dateadd(month,#month-1,#date)
set #date = dateadd(day,#day-1,#date)
if #date <= getdate()-1
set #date = dateadd(year,1,#date)
select #date
Alternatively, to create a string in YYYYMMDD format:
set #date =
right('0000'+convert(char(4),year(getdate())),4)
+ right('00'+convert(char(2),#month),2)
+ right('00'+convert(char(2),#day),2)
Another method, which avoids literals all together:
declare #month tinyint
declare #day tinyint
set #month = 6
set #day = 24
declare #date datetime
declare #today datetime
-- get todays date, stripping out the hours and minutes
-- and save the value for later
set #date = floor(convert(float,getdate()))
set #today = #date
-- add the appropriate number of months and days
set #date = dateadd(month,#month-month(#date),#date)
set #date = dateadd(day,#day-day(#date),#date)
-- increment year by 1 if necessary
if #date < #today set #date = dateadd(year,1,#date)
select #date
Here is my sql example so far. I don't really like it though...
DECLARE #month tinyint,
#day tinyint,
#date datetime
SET #month = 1
SET #day = 1
-- SET DATE TO DATE WITH CURRENT YEAR
SET #date = CONVERT(datetime, CONVERT(varchar,#month) + '/' + CONVERT(varchar,#day) + '/' + CONVERT(varchar,YEAR(GETDATE())))
-- IF DATE IS BEFORE TODAY, ADD ANOTHER YEAR
IF (DATEDIFF(DAY, GETDATE(), #date) < 0)
BEGIN
SET #date = DATEADD(YEAR, 1, #date)
END
SELECT #date
Here's a solution with PostgreSQL
your_date_calculated = Year * 10000 + Month * 100 + Day
gives you a date like 20090623.
select cast( cast( your_date_calculated as varchar ) as date ) + 1
Here's my version. The core of it is just two lines, using the DATEADD function, and it doesn't require any conversion to/from strings, floats or anything else:
DECLARE #Month TINYINT
DECLARE #Day TINYINT
SET #Month = 9
SET #Day = 7
DECLARE #Result DATETIME
SET #Result =
DATEADD(month, ((YEAR(GETDATE()) - 1900) * 12) + #Month - 1, #Day - 1)
IF (#Result < GETDATE())
SET #Result = DATEADD(year, 1, #Result)
SELECT #Result