How can I add hours and minutes in a single query?
I tried this
Select DATEADD(hh,23.59,CAST('2016-07-08' AS DATETIME))
I need to ad 23 hours and 59 minutes, but my code only adds the hours. Why?
How about this?
Select DATEADD(minute, 23*60 + 59, CAST('2016-07-08' AS DATETIME))
EDIT:
If you are getting a float/decimal value such as 23.59, then you can do:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm - FLOOR(#hhmm)) * 100, CAST('2016-07-08' AS DATETIME))
Note: You can also use:
Select DATEADD(minute, FLOOR(#hhmm) * 60 + (#hhmm % 1) * 100, CAST('2016-07-08' AS DATETIME))
But I find this usage of the modulo operator slightly off-kilter.
Use the below code for adding time part to a date.
SELECT DATEADD(Day, DATEDIFF(Day, 0, CAST('2016-07-08' AS DATETIME)), '23:59:00.000')
You can also use DATEADD() twice:
Select DATEADD(minute,59,DATEADD(hh,23,CAST('2016-07-08' AS DATETIME)))
The datepart argument, in your case hh, is part of date to which an integer number is added. So the DATEADD function just ignores any fractional part of your input.
To get result you want, you need to either use DATEADD twice, adding 23 hours and then 59 minutes, or add one day to your date and subtract 1 minute, like this:
Select DATEADD(MI, -1, CAST('2016-07-08' AS DATETIME) + 1)
See also Microsoft's documentation on DATEADD.
another method : you can do by adding one day and then substract minute
Output is same
select DATEADD(minute, -1, DATEADD(DAY, 1,CAST('2016-07-08' AS DATETIME)))
Related
I have column with time stamp data like this
2021-12-09 08:01:00.520
I want to remove the minutes and second and then convert the date to UTC timezone in one line.
I tried this code
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, Time_Stamp), 0) From Table1
I get this result
2021-12-09 08:00:00.000
and I tried this code
SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), Time_Stamp)From Table1
I get this result
2021-12-09 16:01:00.520
What I expected is
2021-12-09 16:00:00.000
How to combine the select statement into one line in simple way
Here is another way.
To remove the minute, seconds and only keep the hour, you may use the following query
DATEADD(HOUR, DATEDIFF(HOUR, 0, Time_Stamp), 0)
To convert to the UTCDate, just find the different in hour () between GETDATE() and GETUTCDATE() (Since you are not interested in the minute and seconds anyway) and add that to the above query
Putting all together
DATEADD(HOUR, DATEDIFF(HOUR, 0, Time_Stamp) + DATEDIFF(HOUR, GETDATE(), GETUTCDATE()), 0)
Convert the date to a string and truncate to remove the minutes and seconds. Then add the difference in minutes between your timezone and UTC.
select dateadd(minute,datediff(minute,getdate(),getutcdate()),convert(datetime2(0),convert(varchar(13),getdate(),126)+':00:00',126));
SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), dateadd(hour, datediff(hour, 0, Time_Stamp), 0)) FROM Table1
I found the following
Select dateadd(minute, datediff(minute,0,GETDATE()) / 15 * 15, 0)
which is great for rounding to the last quarter of the hour. But I would like to always get the last quarter of the last hour.
e.g.,
If time is 12:35 am I want to see 11:45 am since that is the last quarter of the hour.
You can use datetimefromparts():
select datetimefromparts(year(dt), month(dt), day(dt), datepart(hour, dt), 45, 0, 0)
from (values (dateadd(hour, -1, getdate()))) v(dt);
This is a bit long winded, just the way my mind works (Gordan's is far more succinct that mine):
DECLARE #time time = '12:35'
SELECT CONVERT(time,DATEADD(MINUTE,45,DATEADD(HOUR, DATEDIFF(HOUR,'00:00',DATEADD(MINUTE, -45, #time)),'00:00')));
Assuming I understand the question, you want to get the current hour of the current minute is between 45 and 59, or the previous hour if the current minute is between 0 and 44 - So here is my suggested solution:
DECLARE #ActualTime DateTime = GetDate()
SELECT #ActualTime As ActualTime, DATETIMEFROMPARTS(YEAR(Now), MONTH(Now), DAY(Now), DATEPART(HOUR, Now), 45, 0, 0) As LastQuarterOfHour
FROM
(
SELECT IIF(DATEPART(MINUTE,#ActualTime) < 45, DATEADD(HOUR, -1, #ActualTime), #ActualTime) As Now
) AS x
I am using SQL 2008/2012.
Query to calculate Minute Difference between two dates.
select DATEDIFF(mi, '9999-08-03 04:20:00.000', '2005-05-22 03:45:09.530')
Error:
The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.
Note : DateDiff_Big not support this version.
Is there any other way to get result. without using DateDiff_Big
So you use a smaller unit and do some arithmetic. But I presume you mean:
select datediff(minute, '2005-05-22 03:45:09.530', '9999-08-03 04:20:00.000')
Normally, one wants the difference to be positive (although that is not related to the answer).
select (convert(bigint, datediff(day, '2100-08-03 04:20:00', '9999-08-03 04:20:00.000')) * 60 * 24) +
datediff(minute, '2005-05-22 03:45:09.530', '2100-08-03 04:20:00')
Does this fit your needs
DECLARE #DT1 datetime = '9999-08-03 04:20:00.000'
DECLARE #DT2 datetime = '2005-05-22 03:45:09.530'
select --DATEDIFF_BIG(mi, #DT1, #DT2),
CONVERT(BIGINT, DATEDIFF(DAY, #DT1, #DT2)) * 24 * 60
+ CONVERT(BIGINT, DATEDIFF(mi, CONVERT(TIME(7), #DT1), CONVERT(TIME(7), #DT2)))
GO
try this type to get Minutes Different
SELECT CONVERT(BIGINT, DATEDIFF(HOUR, '2005-05-22 03:45:09.530', '9999-08-03 04:20:00.000')) * 60
Check This.
SELECT
CAST(DATEDIFF(hour, '9999-08-03 04:20:00.000', '2009-05-22 03:45:09.530') AS BIGINT)* 60+
DATEDIFF(mi, CONVERT(TIME, '9999-08-03 04:20:00.000'),
CONVERT(TIME, '2009-05-22 03:45:09.530'))+60;
DATEDIFF has a limit that depends on what time element is used.
Because it can only return a number that fits in an INT.
For a return value out of range for int (-2,147,483,648 to
+2,147,483,647), DATEDIFF returns an error. For millisecond, the maximum difference between startdate and enddate is 24 days, 20 hours,
31 minutes and 23.647 seconds. For second, the maximum difference is
68 years.
For minutes that appears to be 4083 years.
So then limit for minutes would be in the -4083 years to 4083 years range.
Then you could wrap the DATEDIFF in a CASE WHEN that checks if it's in that range.
And let it default to the DATEDIFF in hours * 60.
It'll loose some minutes for the default, but that might still be better than returning a NULL.
SELECT dt1, dt2,
DATEDIFF(year, dt1, dt2) AS diff_years,
DATEDIFF(hour, dt1, dt2) AS diff_hours,
CONVERT(BIGINT,
CASE
WHEN DATEDIFF(year, dt1, dt2) BETWEEN -4083 AND 4083
THEN DATEDIFF(minute, dt1, dt2)
ELSE CONVERT(BIGINT,DATEDIFF(hour, dt1, dt2)) * 60
END) AS diff_minutes
FROM (VALUES
('9999-08-03 04:20:00.000', '2005-05-22 03:45:09.530'),
('6083-01-01 00:00:00.000', '2000-01-01 00:00:00.000'),
('2000-01-01 00:00:00.000','6083-01-01 00:00:00.000'),
('0001-01-01 00:00:00.000','9999-12-31 00:00:00.000')
) q(dt1, dt2)
I am trying to get a smalldatetime value of "9pm today" in a query. I thought I could use
DATEADD(HOUR, 21, CONVERT(date, GETDATE()))
but SQL Server doesn't like that - I get the error
The datepart hour is not supported by date function dateadd for data
type date.
Suggestions for a workaround?
Pretty simple, just cast date back to datetime after casting to date.
Thus you'll get current_date 00:00:00 and then add 21 hours:
select dateadd(hh, 21, cast(cast(getdate() as date) as datetime))
it is because dateadd's 3rd parameter should be datetime type, not date.
SELECT DATEADD(HOUR, 21, CONVERT(datetime,CONVERT(date, GETDATE())))
just add 21 / 24.0 to todays date
Select dateadd(day, datediff(day, 1, getDate()), 1) + (21 / 24.0)
First part, dateadd(day, datediff(day, 1, getDate()), 1), strips time from getdate(),
second part, + (21 / 24.0), adds fractional part of day equal to 9 am
This works because internally, SQL Server represents datetimes as two integers, one for the date, (number of days since 1 Jan 1900), and a second integer for the time, (number of ticks since midnight), which it combines into a decimal value where the integer part is the date integer, and the decimal part is the fraction of one day, so if you add 0.5 to a date, you get noon on that day, etc.
or, for comparison, using dateadd for hours,
Select dateadd(hour, 21, dateadd(day, datediff(day, 1, getDate()), 1))
I need to calculate the total length in terms of Hours, Minutes, Seconds, and the average length, given some data with start time and end time.
For example the result must be something like 45:15:10 which means 45 hours 15 min 10 sec, or 30:07 for 30 min 07 sec.
We're using SQL Server 2008 R2 and the conversion failed when time is more than 24:59:59. Any idea of how I could do this?
For information, the columns in the table are Id, StartDateTime, EndDateTime, etc. I need to make a monthly report which contains the recordings count of the month, the total length of these records, and the average length. I'd like to know if there is an easy way to perform all of this.
You shouldn't be converting to time - it is meant to store a point in time on a single 24h clock, not a duration or interval (even one that is constrained on its own to < 24 hours, which clearly your data is not). Instead you can take the datediff in the smallest interval required (in your case, seconds), and then perform some math and string manipulation to present it in the output format you need (it might also be preferable to return the seconds to the application or report tool and have it do this work).
DECLARE #d TABLE
(
id INT IDENTITY(1,1),
StartDateTime DATETIME,
EndDateTime DATETIME
);
INSERT #d(StartDateTime, EndDateTime) VALUES
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())),
(GETDATE() , DATEADD(MINUTE, 22, GETDATE())),
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())),
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE()));
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
Results:
id StartDateTime EndDateTime delta_HH:MM:SS avg_HH:MM:SS
-- ------------------- ------------------- -------------- ------------
1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00 42:10:33
2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00 42:10:33
3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00 42:10:33
4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14 42:10:33
This isn't precisely what you asked for, as it won't show just MM:SS for deltas < 1 hour. You can adjust that with a simple CASE expression:
;WITH x AS (SELECT id, StartDateTime, EndDateTime,
d = DATEDIFF(SECOND, StartDateTime, EndDateTime),
a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER()
FROM #d
)
SELECT id, StartDateTime, EndDateTime,
[delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN
CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2),
[avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN
CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END
+ RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2)
+ ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2)
FROM x;
This query changes the delta column in the 2nd row in the above result from 0:22:00 to 22:00.
I slightly modified Avinash's answer as it may end with error if difference is too big. If you need only HH:mm:ss it is sufficient to distinguish at seconds level ony like this:
SELECT CONVERT(time,
DATEADD(s,
DATEDIFF(s,
'2018-01-07 09:53:00',
'2018-01-07 11:53:01'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
SELECT CONVERT(time,
DATEADD(mcs,
DATEDIFF(mcs,
'2007-05-07 09:53:00.0273335',
'2007-05-07 09:53:01.0376635'),
CAST('1900-01-01 00:00:00.0000000' as datetime2)
)
)
If you want to do averages, then the best approach is to convert to seconds or fractions of a day. Day fractions are convenient in SQL Server, because you can do things like:
select avg(cast(endtime - starttime) as float)
from t
You can convert it back to a datetime using the reverse cast:
select cast(avg(cast(endtime - starttime as float) as datetime)
from t
The arithmetic to get the times in the format you want . . . that is a pain. You might consider including days in the final format, and using:
select right(convert(varchar(255), <val>, 120), 10)
To get the hours exceeding 24, here is another approach:
select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6)
It uses convert for minutes and seconds, which should be padded with 0s on the left. It then appends the hours as a separate value.
Starting in SQL SERVER 2012, you don't need to use DATEDIFF function. You can use FORMAT function to achieve what you want:
SELECT
FORMAT(CONVERT(TIME, [appoitment].[Start] - [appointment].[End]), N'hh\:mm') AS 'Duration'
FROM
[tblAppointment] (NOLOCK)
A way that avoids overflows and can include days and go all the way to milliseconds in the output:
DECLARE #startDate AS DATETIME = '2018-06-01 14:20:02.100'
DECLARE #endDate AS DATETIME = '2018-06-02 15:23:09.000'
SELECT CAST(DATEDIFF(day,'1900-01-01', #endDate - #startDate) AS VARCHAR) + 'd ' + CONVERT(varchar(22), #endDate - #startDate, 114)
The above will return
1d 01:03:06:900
And, off course, you can use the formatting of your choice
SQL Supports datetime substraction which outputs a new datetime relative to the MIN date (for instance 1900-01-01, you can probably get this value from some system variable) This works better than DATEDIFF, because DATEDIFF will count ONE for each "datepart boundaries crossed", even if the elapsed time is less than a whole datapart. Another nice thing about this method is that it allows you to use the date formatting conversions.
If days is the (positive) number of days, like 0.5 for 12 hours, use this expression to format it as a proper duration:
CONVERT(varchar(9), FLOOR(days * 24)) + RIGHT(CONVERT(char(19), CAST(days AS datetime), 120), 6)
Excel will understands values up to 9999:59:59 when pasted. There apply a custom format: [h]:mm:ss in the English version ([u]:mm:ss for Dutch).