Convert an Integer to time - sql

I am being supplied a single integer that is supposed to represent an hour. So If it returns 1 it is 1:00 am and so forth on a 24 hour clock,13 for example is 1:00 pm. I need to convert this into time in SQL.
I know in MYSQL they have a function which does this:
SEC_TO_TIME(TheHour*60*60)
Is there an equivalent I can use in SQL? How do I do this?

You could do something like this.
select cast(DATEADD(hour, 13, 0) as time)
The upside is that it will still work even with negative numbers or values over 24.

There are two T-SQL function:
DATEFROMPARTS ( year, month, day )
and
TIMEFROMPARTS ( hour, minute, seconds, fractions, precision )
then you can use CONVERT if you need to format it.

-- test data
declare #hour_table table(hour_number int)
while (select count(*) from #hour_table) < 24
begin
insert into #hour_table(hour_number)
select count(*) from #hour_table
end
-- return results with your conversion to time string
select
hour_number,
convert(varchar(8),timefromparts( hour_number, 0, 0, 0, 0 ),0) as time_string
from #hour_table

Related

How do I convert a 5 or 6 digit decimal to a date in sql

I've got a column that shows the date as a decimal such as 101118 for 10-11-18 and 90118 for 09-01-18. I am trying to create a simple report that would give me all reservations yesterday.
So for example
Select playerid, datereservationmade
from dbo.lms
normally there is very simple and I would just do
Select playerid, datereservationmade
from dbo.lms
where datereservationmade >= dateadd(day,datediff(day,1,GETDATE()),0)
AND datereservationmade < dateadd(day,datediff(day,0,GETDATE()),0)
That does not work in this case because the datereservationmade field is a decimal and if its a month 1-9 it leaves off the 0 and makes it a 5 digit decimal then if its 10-12 it is a 6 digit decimal.
Someone please help me figure out how to convert this!
If at all possible, you really should fix your schema so that dates are actually being stored as dates.
If you need to work with the decimal data type, you can use something like the following...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
BEGIN DROP TABLE #TestData; END;
CREATE TABLE #TestData (
decimal_date DECIMAL(6, 0) NOT NULL
);
INSERT #TestData (decimal_date) VALUES (101118), (90118), (101718);
--==============================================
SELECT
td.decimal_date,
dd.date_date
FROM
#TestData td
CROSS APPLY ( VALUES (RIGHT('0' + CONVERT(VARCHAR(6), td.decimal_date), 6)) ) cd (char_date)
CROSS APPLY ( VALUES (CONVERT(DATE, STUFF(STUFF(cd.char_date, 5, 0, '/'), 3, 0, '/'), 1)) ) dd (date_date)
WHERE
dd.date_date = CONVERT(DATE, DATEADD(DAY, -1, GETDATE()));
Convert the decimal to varchar(6) by adding a zero in front and getting the RIGHT 6 characters.
Then convert the string to a date from its parts, which are substrings in your varchar(6). This is made easier in SQL Server 2012 with the DATEFROMPARTS function.
Using the DATEFROMPARTS, as Tab Alleman suggested, you might get something like this:
-- Example of the arithmetic
SELECT 101118 / 10000 AS Month, (101118 % 10000) / 100 AS Day, (101118 % 100) AS Year
-- Using the math in DATEFROMPARTS
SELECT DATEFROMPARTS((101118 % 100) + 2000, 101118 / 10000, (101118 % 10000) / 100 )
However, I'm skeptical that you've provided all the correct information. What happens on January first? Your decimal value won't start with zero (as you stated). Will your day always pad with zero? If not, then 1119 won't produce the same result as 10119. If, however, your day does start with zero, then the equation above should work fine.

round GETDATE (SQL Server)

I have a function which is working fine in MySQL
round((now()-ts/60) as tdiff
(round the result of subtracting the current datetime from ts (also a datetime) divided by 60)
Attempting (and failing) to convert this for SQL Server.
Tried -
round((GETDATE()-ts/60) as tdiff
but that results in round function requires 2 or 3 parameters (which to me it does), so modified to -
round((GETDATE()-ts/60,0) as tdiff
but that results in the datatypes (GETDATE and ts) are incompatible in the subtract operator.
So then I attempted to cast both GETDATE and ts as date and that made no difference.
ts is a conventional datetime i.e.
2918-04-20 11:05:09 and I assumed GETDATE returned the same format.
As an example if GETDATE is today and ts is 2018-04-20 11:05:09 then tdiff is
6850891 (round effectively removes the dashes and colons and concatenates the datetime producing 20180420110509 for 2018-04-20 11:05:09 and 20180831164000 for 2018-08-31 16:40:00 and then divides by 60 to get 6850891.
Is there a remedy for this?
Regards, Ralph
GETDATE(), as per the documentation, returns a datetime. A datetime is accurate to 1/300 of a second, and it's accuracy cannot be changed.
If you want the time accurate to a second, you need to convert to a datetime2(0):
SELECT CONVERT(datetime2(0),GETDATE());
Also, however, don't use syntax like GETDATE()-ts. use the functions DATEADD and DATEDIFF for date maths.
I've no idea what GETDATE()-ts/60 is trying to acheive. Perhaps the number of minutes between the 2? DATEDIFF counts the "ticks" between 2 dates/times, thus DATEDIFF(MINUTE,'00:00:59','00:01:00') would return 1, despite there only being 1 second between the 2 times. This is because the minute value has "ticked" once (from 0 to 1). Therefore you might want to use DATEDIFF(SECOND,'00:00:59','00:01:00') / 60. This would return 0, as 1 / 60 in integer math is 0 (as is 59 / 60).
I think you want to use the DATEDIFF function:
DATEDIFF ( datepart , startdate , enddate )
DATEDIFF ( second, ts, GETDATE())
DATEDIFF ( second, ts, GETDATE())
DATEDIFF ( minute, ts, GETDATE())
DATEDIFF ( hour, ts, GETDATE())
The first argument tells it which increment of time to return.
If you are trying to find the difference between two values, then use datediff(). For instance:
select datediff(day, getdate(), ts)
gets the difference in days.
date_diff() or a related function would also be the right approach in MySQL.
sorry, I don't know if I have understand the question, you need to do date-date/60 and round the result?
In this case you have to change the minus ("-") with the DATEDIFF("Type return example DAYS", GETDATE(), ts).
So you will have ROUND((DATEDIFF(DAY,GETDATE(),ts)/60,0)
Please try and let me know if it will works for you
Bye

How to perform arithmetic function in DATE TIME in SQL

I have four columns namely-
1. C_Date in YYYYMMDD format (varchar(255)) Eg. 20161231
2. C_Time in 4-digit Military format (varchar(255)) Eg. 2143
3. E_Date in YYYYMMDD format (varchar(255)) Eg. 20161230
4. E_Time in 4-digit Military format (varchar(255)) Eg. 1600
I want to Calculate the time between E event and C event. How can i perform this computation with a select statement?
Pretty simple to create a date type from the component values:
with data as (select '20161231' as c_date, '2143' as c_time)
select
convert(
datetime,
stuff(stuff(stuff(c_date + ' ' + c_time, 12, 0, ':'), 7, 0, '-'), 5, 0, '-'),
120
) as c_datetime
from data;
Use datediff() to calculate the time difference. You didn't specify how you wanted the output to look so I won't attempt a guess. There should be a hundred other questions out there with information relevant to your question though.
Also note that I did not append ':00' to the string to represent seconds. It seems to work though I couldn't track down an official document to confirm that. So to be safe you may want to tack that on as well. Arguably there could be a more universal format like ISO 8601 that would be a "better" solution. You get the idea though.
A small matter to convert your strings into a datetime. Then we use DateDiff() to calculate the differance between the two dates.
Declare #YourTable table (C_Date varchar(255),C_Time varchar(255),E_Date varchar(255),E_Time varchar(255))
Insert Into #YourTable values
('20161231','2143','20161230','1600')
;with cte as (
Select *
,CDT = try_convert(DateTime,C_Date+' '+stuff(C_Time,3,0,':'))
,EDT = try_convert(DateTime,E_Date+' '+stuff(E_Time,3,0,':'))
from #YourTable
)
Select CDT
,EDT
,Duration = concat(DateDiff(DD,EDT,CDT),' ',Format(DateAdd(Second,DateDiff(SECOND,EDT,CDT),'1899-12-31'),'HH:mm:ss'))
,AsSeconds = DateDiff(SECOND,EDT,CDT)
,AsMinutes = DateDiff(MINUTE,EDT,CDT)
From cte
Returns
CDT EDT Duration AsSeconds AsMinutes
2016-12-31 21:43:00 2016-12-30 16:00:00 1 05:43:00 106980 1783

SQL convert single int to a time value

I am trying to convert a single integer which represents the hour value into a time. I've tried using cast but this converts the value to a date
cast(datepart(hh,tstart) as datetime) as test
I've also tried casting it as a time and the conversion is not allowed.
The numbers I am working with are 7,8,9,10,11,12,13,...,23, 0
The format I would like is convert 7 to 7:00, 23 to 23:00, etc
Thank you
There are many ways to do that:
WITH table_name AS
(
SELECT * FROM (VALUES
(1),(2),(3),(10),(23)
) T(H)
)
SELECT DATEADD(HOUR, H, 0) DateValue,
CONVERT(time, DATEADD(HOUR, H, 0)) TimeValue,
CONVERT(varchar(2), H)+':00' TextValue
FROM table_name T1
I would recomend storing value as TIME datatype.
You can try this:
select cast(dateadd(hour,3,'00:00:00') as time)
which gives result:
03:00:00.0000000
Use your int values in place of 3 in above statement
Use convert datetime to varchar datatype and use case statement
DECLARE #date datetime ='2016-05-01 10:00:000'
SELECT CASE cast(DATEPART(hh,#date)as varchar(10))
WHEN '10'then '10:00'
WHEN '11'then '11:00'
WHEN '12'then '12:00'
.
.
.
WHEN '23' then '23:00'
END 'Hourpart'
You can concatenate a minute to the time and cast it to time
select cast(concat(20,':00') as time(7)) as 'time'
If you wanted to display like 'HH:MM',use the below query.
SELECT CAST(23 AS VARCHAR(50))+':00'
If you wanted to get the result as time format,use the below query.
SELECT CAST(CAST(23 AS VARCHAR(50))+':00:00' AS TIME)
OR
SELECT CAST(DATEADD(HOUR,23,'00:00:00') as time)
here is the sample output :
Assuming all of your potential values are integers between 1 and 24, I think FORMAT is the simplest way.
FORMAT(tstart*100,'00:00')

convert Excel Date Serial Number to Regular Date

I got a column called DateOfBirth in my csv file with Excel Date Serial Number Date
Example:
36464
37104
35412
When i formatted cells in excel these are converted as
36464 => 1/11/1999
37104 => 1/08/2001
35412 => 13/12/1996
I need to do this transformation in SSIS or in SQL. How can this be achieved?
In SQL:
select dateadd(d,36464,'1899-12-30')
-- or thanks to rcdmk
select CAST(36464 - 2 as SmallDateTime)
In SSIS, see here
http://msdn.microsoft.com/en-us/library/ms141719.aspx
The marked answer is not working fine, please change the date to "1899-12-30" instead of "1899-12-31".
select dateadd(d,36464,'1899-12-30')
You can cast it to a SQL SMALLDATETIME:
CAST(36464 - 2 as SMALLDATETIME)
MS SQL Server counts its dates from 01/01/1900 and Excel from 12/30/1899 = 2 days less.
tldr:
select cast(#Input - 2e as datetime)
Explanation:
Excel stores datetimes as a floating point number that represents elapsed time since the beginning of the 20th century, and SQL Server can readily cast between floats and datetimes in the same manner. The difference between Excel and SQL server's conversion of this number to datetimes is 2 days (as of 1900-03-01, that is). Using a literal of 2e for this difference informs SQL Server to implicitly convert other datatypes to floats for very input-friendly and simple queries:
select
cast('43861.875433912' - 2e as datetime) as ExcelToSql, -- even varchar works!
cast(cast('2020-01-31 21:00:37.490' as datetime) + 2e as float) as SqlToExcel
-- Results:
-- ExcelToSql SqlToExcel
-- 2020-01-31 21:00:37.490 43861.875433912
this actually worked for me
dateadd(mi,CONVERT(numeric(17,5),41869.166666666664)*1440,'1899-12-30')
(minus 1 more day in the date)
referring to the negative commented post
SSIS Solution
The DT_DATE data type is implemented using an 8-byte floating-point number. Days are represented by whole number increments, starting with 30 December 1899, and midnight as time zero. Hour values are expressed as the absolute value of the fractional part of the number. However, a floating point value cannot represent all real values; therefore, there are limits on the range of dates that can be presented in DT_DATE. Read more
From the description above you can see that you can convert these values implicitly when mapping them to a DT_DATE Column after converting it to a 8-byte floating-point number DT_R8.
Use a derived column transformation to convert this column to 8-byte floating-point number:
(DT_R8)[dateColumn]
Then map it to a DT_DATE column
Or cast it twice:
(DT_DATE)(DT_R8)[dateColumn]
You can check my full answer here:
Is there a better way to parse [Integer].[Integer] style dates in SSIS?
Found this topic helpful so much so created a quick SQL UDF for it.
CREATE FUNCTION dbo.ConvertExcelSerialDateToSQL
(
#serial INT
)
RETURNS DATETIME
AS
BEGIN
DECLARE #dt AS DATETIME
SELECT #dt =
CASE
WHEN #serial is not null THEN CAST(#serial - 2 AS DATETIME)
ELSE NULL
END
RETURN #dt
END
GO
I had to take this to the next level because my Excel dates also had times, so I had values like this:
42039.46406 --> 02/04/2015 11:08 AM
42002.37709 --> 12/29/2014 09:03 AM
42032.61869 --> 01/28/2015 02:50 PM
(also, to complicate it a little more, my numeric value with decimal was saved as an NVARCHAR)
The SQL I used to make this conversion is:
SELECT DATEADD(SECOND, (
CONVERT(FLOAT, t.ColumnName) -
FLOOR(CONVERT(FLOAT, t.ColumnName))
) * 86400,
DATEADD(DAY, CONVERT(FLOAT, t.ColumnName), '1899-12-30')
)
In postgresql, you can use the following syntax:
SELECT ((DATE('1899-12-30') + INTERVAL '1 day' * FLOOR(38242.7711805556)) + (INTERVAL '1 sec' * (38242.7711805556 - FLOOR(38242.7711805556)) * 3600 * 24)) as date
In this case, 38242.7711805556 represents 2004-09-12 18:30:30 in excel format
In addition of #Nick.McDermaid answer I would like to post this solution, which convert not only the day but also the hours, minutes and seconds:
SELECT DATEADD(s, (42948.123 - FLOOR(42948.123))*3600*24, dateadd(d, FLOOR(42948.123),'1899-12-30'))
For example
42948.123 to 2017-08-01 02:57:07.000
42818.7166666667 to 2017-03-24 17:12:00.000
You can do this if you just need to display the date in a view:
CAST will be faster than CONVERT if you have a large amount of data, also remember to subtract (2) from the excel date:
CAST(CAST(CAST([Column_With_Date]-2 AS INT)AS smalldatetime) AS DATE)
If you need to update the column to show a date you can either update through a join (self join if necessary) or simply try the following:
You may not need to cast the excel date as INT but since the table I was working with was a varchar I had to do that manipulation first. I also did not want the "time" element so I needed to remove that element with the final cast as "date."
UPDATE [Table_with_Date]
SET [Column_With_Excel_Date] = CAST(CAST(CAST([Column_With_Excel_Date]-2 AS INT)AS smalldatetime) AS DATE)
If you are unsure of what you would like to do with this test and re-test! Make a copy of your table if you need. You can always create a view!
Google BigQuery solution
Standard SQL
Select Date, DATETIME_ADD(DATETIME(xy, xm, xd, 0, 0, 0), INTERVAL xonlyseconds SECOND) xaxsa
from (
Select Date, EXTRACT(YEAR FROM xonlydate) xy, EXTRACT(MONTH FROM xonlydate) xm, EXTRACT(DAY FROM xonlydate) xd, xonlyseconds
From (
Select Date
, DATE_ADD(DATE '1899-12-30', INTERVAL cast(FLOOR(cast(Date as FLOAT64)) as INT64) DAY ) xonlydate
, cast(FLOOR( ( cast(Date as FLOAT64) - cast(FLOOR( cast(Date as FLOAT64)) as INT64) ) * 86400 ) as INT64) xonlyseconds
FROM (Select '43168.682974537034' Date) -- 09.03.2018 16:23:28
) xx1
)
For those looking how to do this in excel (outside of formatting to a date field) you can do this by using the Text function https://exceljet.net/excel-functions/excel-text-function
i.e.
A1 = 132134
=Text(A1,"MM-DD-YYYY") will result in a date
This worked for me because sometimes the field was a numeric to get the time portion.
Command:
dateadd(mi,CONVERT(numeric(17,5),41869.166666666664)*1440,'1899-12-31')