Combining Date and Time using DATEADD and DATEDIFF - sql

I'm trying to create a new column by combining the date and time variables. For example, the data table looks like this and "StartDateTime" is the new variable I want to create.
Date StartTime *StartDateTime*
2014-03-20 1900-01-01 10:00:00.000 2014-03-30 10:00:00.000
2015-09-23 1900-01-01 11:00:00.000 2015-09-23 11:00:00.000
I used the cast function and it seems like my current code is working.
select *,
(cast(Date as datetime) + cast(StartTime as datetime)) as StartDateTime
from my_table
But I just saw this line of code on a random website and it seems like it does the same thing. However, I didn't really get the logic behind it.
select *,
DATEADD(day, 0, DATEDIFF(day, 0, Date)) + DATEADD(day, 0 -DATEDIFF(day, 0, StartTime), StartTime) As StartDateTime
from my_table
I believe the first part DATEADD(day, 0, DATEDIFF(day, 0, Date)) just returns the original date but I don't really get the second part. My understanding is DATEDIFF(day, 0, StartTime) would just return 0 and I'm not sure why 0 -DATEDIFF(day, 0, StartTime) is necessary.
Thank you.

This is one way to combine the date and time values into a single DateTime2:
declare #Samples as Table ( StartDate Date, StartTime DateTime2 );
insert into #Samples ( StartDate, StartTime ) values
( '2014-03-20', '1900-01-01 10:00:00.000' ),
( '2015-09-23', '1900-01-01 11:00:00.000' );
select StartDate, StartTime,
-- Demonstrate how to get the time with millisecond resolution from StartTime .
Cast( StartTime as Time(3) ) as StartTimeAsTime,
-- Combine the time from StartTime with the date from StartDate .
-- Get the time, convert it to milliseconds after midnight, and add it to the date as a DateTime2 .
DateAdd( ms, DateDiff( ms, 0, Cast( StartTime as Time(3) ) ), Cast( StartDate as DateTime2 ) ) as StartDateTime
from #Samples;

I have no idea what that code is doing. And the add operator is also not supported by all datetime datatypes. The correct solution is:
select *
, dateadd(second, datepart(second, StartTime), dateadd(minute, datepart(minute, StartTime), dateadd(hour, datepart(hour, StartTime), [Date])))
from (values (convert(datetime2(0),'2014-03-20'), convert(time,'10:00:00.000'))) as X ([Date], StartTime);
Ideally you would store your StartTime value in a time datatype. But the above code will still work with a datetime2 datetype (which is the recommended form of datetime to use).

Related

available room booking between two dates and and two times column sql server

i have four columns in my table.
STARTDATE STARTTIME ENDDATE ENDTIME ROOMCODE
2018-10-16 00:00:00.000 14:00 2018-10-16 00:00:00.000 18:00 CS0001
2018-10-16 00:00:00.000 18:00 2018-10-16 00:00:00.000 22:00 CS0001
i want to check booking is available or not
select CONFERENCE_ROOM from COR_CONFERENCE_BOOKING where
(cast(STARTDATE as datetime) + cast(START_TIME as time) >= cast('2018-10-16'
as datetime) + cast(DATEADD(MINUTE, 01, '14:00') as time)
and cast(STARTDATE as datetime) + cast(START_TIME as time) < cast('2018-10-
16' as datetime) + cast('18:00' as time))
or (cast(ENDDATE as datetime) + cast(END_TIME as time) >= cast('2018-10-16'
as datetime) + cast(DATEADD(MINUTE, 01, '14:00') as time)
and cast(ENDDATE as datetime) + cast(END_TIME as time) < cast('2018-10-16'
as datetime) + cast('18:00' as time))
and CONFERENCE_ROOM='CS0001'
problem is there i want to select the data if any data found on select query on passing date and time then room is booked otherwise its free.
please solve this query. Its too complicated for me.
Here's an example snippet for MS SQL Server.
I'm assuming that this is your target RDBMS because the example SQL uses that DATEADD function.
It'll only return the first record from the table variable.
Because the second record is out of the range.
declare #Table table (
ID INT PRIMARY KEY IDENTITY(1,1),
STARTDATE date,
STARTTIME time,
ENDDATE date,
ENDTIME time,
CONFERENCE_ROOM varchar(6)
);
insert into #Table (STARTDATE, STARTTIME, ENDDATE, ENDTIME, CONFERENCE_ROOM) values
('2018-10-16','14:00:00','2018-10-16','18:00:00','CS0001'),
('2018-10-16','18:00:00','2018-10-16','22:00:00','CS0001');
select ID, CONFERENCE_ROOM
from #Table t
where (CAST(STARTDATE AS DATETIME) + CAST(STARTTIME as DATETIME)) < (CAST(ENDDATE AS DATETIME) + CAST(ENDTIME as DATETIME))
and (CAST(STARTDATE AS DATETIME) + CAST(STARTTIME as DATETIME)) >= CAST('2018-10-16 14:00' AS DATETIME)
and (CAST(ENDDATE AS DATETIME) + CAST(ENDTIME as DATETIME)) <= CAST('2018-10-16 18:00' AS DATETIME)
and CONFERENCE_ROOM = 'CS0001';
If the STARTTIME & ENDTIME are VARCHAR's instead of TIME data types?
Then to avoid errors with trying to convert crap data, you could use TRY_CAST instead.
(If TRY_CAST is available on your version of MS SQL Server)
Because instead of an error a TRY_CAST would return NULL when the conversion fails.
Example:
select ID, CONFERENCE_ROOM
from #Table t
where STARTDATE = ENDDATE
and TRY_CAST(STARTTIME AS TIME) < TRY_CAST(ENDTIME AS TIME)
and STARTDATE = CAST('2018-10-16' AS DATE)
and TRY_CAST(STARTTIME AS TIME) >= CAST('14:00' AS TIME)
and TRY_CAST(ENDTIME AS TIME) <= CAST('18:00' AS TIME)
and CONFERENCE_ROOM = 'CS0001';

Difference between date and current date, if statement?

I have a table with four columns:
id;
datefrom;
dateto;
user id.
I need to calculate the difference between datefrom and dateto (datefrom-dateto) in hours, add this difference into additional column. The main thing is that some cells of dateto are empty. In this case I should take "dateto" as current date and time.
The second thing is to add column with if statment. If the difference between datefrom and dateto more than 3 hours than 1, else 0.
Now I can calculate only differences in hours. The main problem is with empty cells and additional column with statement when hours more than 3
select id, DateFrom, DateTo, UserId,
(Datefrom-DateTO) as hours
from table
order by id
enter image description here
Here is a good example for MS SQL:
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate ='2007-06-05'
SET #EndDate ='2007-08-05'
SELECT DATEDIFF(Hour, #StartDate, #EndDate) AS NewDate
--Return Value = 1464 Hour
SELECT DATEDIFF(minute, #StartDate, #EndDate) AS NewDate
--Return Value = 87840 minute
SELECT DATEDIFF(second, #StartDate, #EndDate) AS NewDate
--Return Value = 5270400 second
You will need some Control Flow Functions.
With the select, you will need:
SELECT id, datefrom, dateto, userid
You can use IFNULL(), if dateto is NULL, then it will return CURDATE():
IFNULL(dateto, CURDATE())
And one IF(condition, truth, false), but first, you will need the diference in hours. You can calculate with some Date and Time Functions, you will get the diference between the dates, convert it to seconds, and divide by 3600):
TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600
Now, check if it's bigger than 3:
IF(TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600 > 3, 1, 0)
At the end, it will be like:
SELECT
id,
datefrom,
dateto,
userid,
TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600
IF(TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600 > 3, 1, 0),
FROM table;
thanks all.
I wrote code in Periscope. I dont know why but I can use there some functions as TIME_TO_SEC, TIMEDIFF, TIMESTAMPDIFF.
The final code is below.
SELECT id
, DateFrom
, DateTo
, UserId
, CASE
WHEN DateFrom is null OR (DateFrom - DateTo) < '0 days 00:00:00'
THEN (NOW() - DateTo)
ELSE (DateFrom - DateTo)
END as hours
, CASE
WHEN (DateFrom IS NULL AND (NOW() - DateTo) > '0 days 03:00:00') OR (DateFrom is not null and ((DateFrom - DateTo) > '0 days 03:00:00') OR (DateFrom - DateTo) < '0 days 00:00:00')
THEN 1
ELSE 0
END as Attribute

How to differentiate two time timeperiod between two columns?

I wanna know how to differentiate a time period in a day between two columns like in time and out time?
DATEDIFF
DATEDIFF (datepart , startdate , enddate)
The datepart you have mentioend in your question is day. You can use any of day, d and dd
Sample
DECLARE #inTime DATETIME, #outTime DATETIME
SET #inTime = '2015-05-01 12:10:09'
SET #outTime = '2015-05-22 05:15:36'
SELECT DATEDIFF(DAY, #inTime, #outTime) AS timedifferentiate
In a query
SELECT ,inTime
,outTime
DATEDIFF(DAY, inTime, outTime) AS timedifferentiate
FROM yourTable
Just use a minus operator, and convert to time
SELECT
CONVERT(time, -- Note the time datatype range is 00:00:00.0000000 through 23:59:59.9999999
CONVERT(datetime, '2015-04-01 19:03') -- Out time
- CONVERT(datetime, '2015-04-01 09:02') -- In time
) TimeDiff

How do I subtract two date columns and two time columns in sql

I have 4 columns that are
Startdate,
enddate,
starttime,
endtime.
I need to get subtractions from the enddate and endtime - startdate and starttime. I will need that answer from the four columns in sql.
so far I have this I found but dont think this will work right.
SELECT DATEDIFF (day, enddate, startdate) as NumberOfDays
DATEDIFF(hour,endtime,starttime) AS NumberOfHours
DATEDIFF(minute,endtime,starttime) AS NumberOfMinutes
from table;
Thanks for your help
EDIT - Now that I realize that the question is for SQL Server 2000, this proposed answer may not work.
The SQL Server 2000 documentation can be found at https://www.microsoft.com/en-us/download/details.aspx?id=18819. Once installed, look for tsqlref.chm in your installed path, and in that help file you can find information specific to DATEDIFF.
Based on the wording of the original question, I'm assuming that the start/end time columns are of type TIME, meaning there is no date portion. With that in mind, the following would answer your question.
However, note that depending on your data, you will lose precision in regards to the seconds and milliseconds.
More about DATEDIFF: https://msdn.microsoft.com/en-us/library/ms189794.aspx
DECLARE #mytable AS TABLE
(
startdate DATETIME,
enddate DATETIME,
starttime TIME,
endtime TIME
)
INSERT INTO #mytable (startdate, enddate, starttime, endtime)
VALUES (GETDATE() - 376, GETDATE(), '00:00:00', '23:59')
SELECT *
FROM #mytable
SELECT DATEDIFF(HOUR, startdate, enddate) AS [NumHours],
DATEDIFF(MINUTE, starttime, endtime) AS [NumMinutes]
FROM #mytable
This would yield output similar to:
Assuming you have data like this, you can add the StartDate to the StartTime to get the StartDateTime, same for the EndDateTime
StartDate StartTime EndDate EndTime
----------------------- ----------------------- ----------------------- -----------------------
2014-05-01 00:00:00.000 1900-01-01 10:53:28.290 2014-05-07 00:00:00.000 1900-01-01 11:55:28.290
Once you've done that you can get the Days, Hours and Minutes like this:
select
DATEDIFF(minute, StartDate + StartTime, EndDate + EndTime) / (24*60) 'Days',
(DATEDIFF(minute, StartDate + StartTime, EndDate + EndTime) / 60) % 24 'Hours',
DATEDIFF(minute, StartDate + StartTime, EndDate + EndTime) % 60 'Minutess'
from YourTable
We have work in minutes the whole time in order to prevent problems with partial days crossing midnight and partial hours crossing an hour mark.

How to combine date from one field with time from another field - MS SQL Server

In an extract I am dealing with, I have 2 datetime columns. One column stores the dates and another the times as shown.
How can I query the table to combine these two fields into 1 column of type datetime?
Dates
2009-03-12 00:00:00.000
2009-03-26 00:00:00.000
2009-03-26 00:00:00.000
Times
1899-12-30 12:30:00.000
1899-12-30 10:00:00.000
1899-12-30 10:00:00.000
You can simply add the two.
if the Time part of your Date column is always zero
and the Date part of your Time column is also always zero (base date: January 1, 1900)
Adding them returns the correct result.
SELECT Combined = MyDate + MyTime FROM MyTable
Rationale (kudos to ErikE/dnolan)
It works like this due to the way the date is stored as two 4-byte
Integers with the left 4-bytes being the date and the right
4-bytes being the time. Its like doing $0001 0000 + $0000 0001 =
$0001 0001
Edit regarding new SQL Server 2008 types
Date and Time are types introduced in SQL Server 2008. If you insist on adding, you can use Combined = CAST(MyDate AS DATETIME) + CAST(MyTime AS DATETIME)
Edit2 regarding loss of precision in SQL Server 2008 and up (kudos to Martin Smith)
Have a look at How to combine date and time to datetime2 in SQL Server? to prevent loss of precision using SQL Server 2008 and up.
If the time element of your date column and the date element of your time column are both zero then Lieven's answer is what you need. If you can't guarantee that will always be the case then it becomes slightly more complicated:
SELECT DATEADD(day, 0, DATEDIFF(day, 0, your_date_column)) +
DATEADD(day, 0 - DATEDIFF(day, 0, your_time_column), your_time_column)
FROM your_table
This is an alternative solution without any char conversions:
DATEADD(ms, DATEDIFF(ms, '00:00:00', [Time]), CONVERT(DATETIME, [Date]))
You will only get milliseconds accuracy this way, but that would normally be OK. I have tested this in SQL Server 2008.
This worked for me
CAST(Tbl.date as DATETIME) + CAST(Tbl.TimeFrom AS TIME)
(on SQL 2008 R2)
If you're not using SQL Server 2008 (i.e. you only have a DateTime data type), you can use the following (admittedly rough and ready) TSQL to achieve what you want:
DECLARE #DateOnly AS datetime
DECLARE #TimeOnly AS datetime
SET #DateOnly = '07 aug 2009 00:00:00'
SET #TimeOnly = '01 jan 1899 10:11:23'
-- Gives Date Only.
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, #DateOnly))
-- Gives Time Only.
SELECT DATEADD(Day, -DATEDIFF(Day, 0, #TimeOnly), #TimeOnly)
-- Concatenates Date and Time parts.
SELECT
CAST(
DATEADD(dd, 0, DATEDIFF(dd, 0, #DateOnly)) + ' ' +
DATEADD(Day, -DATEDIFF(Day, 0, #TimeOnly), #TimeOnly)
as datetime)
It's rough and ready, but it works!
If both of your fields are datetime then simply adding those will work.
eg:
Declare #d datetime, #t datetime
set #d = '2009-03-12 00:00:00.000';
set #t = '1899-12-30 12:30:00.000';
select #d + #t
If you used Date & Time datatype then just cast the time to datetime
eg:
Declare #d date, #t time
set #d = '2009-03-12';
set #t = '12:30:00.000';
select #d + cast(#t as datetime)
This was my solution which ignores the date value of the time column
CAST(Tbl.date as DATETIME) + CAST(CAST(Tbl.TimeFrom AS TIME) as DATETIME)
Hope this helps others
Convert the first date stored in a datetime field to a string, then convert the time stored in a datetime field to string, append the two and convert back to a datetime field all using known conversion formats.
Convert(datetime, Convert(char(10), MYDATETIMEFIELD, 103) + ' ' + Convert(char(8), MYTIMEFIELD, 108), 103)
Convert both field into DATETIME :
SELECT CAST(#DateField as DATETIME) + CAST(#TimeField AS DATETIME)
and if you're using Getdate() use this first:
DECLARE #FechaActual DATETIME = CONVERT(DATE, GETDATE());
SELECT CAST(#FechaActual as DATETIME) + CAST(#HoraInicioTurno AS DATETIME)
I had many errors as stated above so I did it like this
try_parse(concat(convert(date,Arrival_date),' ',arrival_time) as datetime) AS ArrivalDateTime
It worked for me.
Finding this works for two dates where you want time from one and date from the other:
declare #Time as datetime = '2021-11-19 12:34'
declare #Date as datetime = '2021-10-10'
SELECT #time + datediff(day, #Time, #Date)
DECLARE #Dates table ([Date] datetime);
DECLARE #Times table ([Time] datetime);
INSERT INTO #Dates VALUES('2009-03-12 00:00:00.000');
INSERT INTO #Dates VALUES('2009-03-26 00:00:00.000');
INSERT INTO #Dates VALUES('2009-03-30 00:00:00.000');
INSERT INTO #Times VALUES('1899-12-30 12:30:00.000');
INSERT INTO #Times VALUES('1899-12-30 10:00:00.000');
INSERT INTO #Times VALUES('1899-12-30 10:00:00.000');
WITH Dates (ID, [Date])
AS (
SELECT ROW_NUMBER() OVER (ORDER BY [Date]), [Date] FROM #Dates
), Times (ID, [Time])
AS (
SELECT ROW_NUMBER() OVER (ORDER BY [Time]), [Time] FROM #Times
)
SELECT Dates.[Date] + Times.[Time] FROM Dates
JOIN Times ON Times.ID = Dates.ID
Prints:
2009-03-12 10:00:00.000
2009-03-26 10:00:00.000
2009-03-30 12:30:00.000
To combine date from a datetime column and time from another datetime column this is the best fastest solution for you:
select cast(cast(DateColumn as date) as datetime) + cast(TimeColumn as datetime) from YourTable
SELECT CAST(CAST(#DateField As Date) As DateTime) + CAST(CAST(#TimeField As Time) As DateTime)
Another way is to use CONCATand CAST, be aware, that you need to use DATETIME2(x) to make it work. You can set x to anything between 0-7 7 meaning no precision loss.
DECLARE #date date = '2018-03-12'
DECLARE #time time = '07:00:00.0000000'
SELECT CAST(CONCAT(#date, ' ', #time) AS DATETIME2(7))
Returns 2018-03-12 07:00:00.0000000
Tested on SQL Server 14
simply concatenate both , but cast them first as below
select cast(concat(Cast(DateField as varchar), ' ', Cast(TimeField as varchar)) as datetime) as DateWithTime from TableName;
select s.SalesID from SalesTbl s
where cast(cast(s.SaleDate as date) as datetime) + cast(cast(s.SaleCreatedDate as time) as datetime) between #FromDate and #ToDate
The existing answers do not address the datetime2 datatype so I will add mine:
Assuming that you want to add a time value to a datetime2 value where:
The datetime2 value could contain non-zero time component and/or fractional seconds
The time value could contain the value 23:59:59.9999999 which is 86,399.9999999 seconds, 86,399,999,999.9 microseconds or 86,399,999,999,900 nanoseconds¹
Due to the limitations of dateadd function¹ you must add them in two steps:
Convert the time value to seconds and use dateadd(second, ...)
Extract the nanoseconds from the time value and use dateadd(nanosecond, ...) to add them to the date calculated above
declare #dv datetime2 = '2000-01-01 12:34:56.7890123';
declare #tv time = '23:59:59.9999999';
select dateadd(
nanosecond,
datepart(nanosecond, #tv),
dateadd(
second,
datepart(hour, #tv) * 60 * 60 + datepart(minute, #tv) * 60 + datepart(second, #tv),
#dv
)
);
-- 2000-01-02 12:34:56.7890122
¹ Nanosecond values might not fit in int datatype which dateadd function expects.
SELECT CAST(your_date_column AS date) + CAST(your_time_column AS datetime) FROM your_table
Works like a charm
I ran into similar situation where I had to merge Date and Time fields to DateTime field. None of the above mentioned solution work, specially adding two fields as the data type for addition of these 2 fields is not same.
I created below solution, where I added hour and then minute part to the date. This worked beautifully for me. Please check it out and do let me know if you get into any issues.
;with tbl
as
(
select StatusTime = '12/30/1899 5:17:00 PM', StatusDate = '7/24/2019 12:00:00 AM'
)
select DATEADD(MI, DATEPART(MINUTE,CAST(tbl.StatusTime AS TIME)),DATEADD(HH, DATEPART(HOUR,CAST(tbl.StatusTime AS TIME)), CAST(tbl.StatusDate as DATETIME)))
from tbl
Result: 2019-07-24 17:17:00.000