How to convert AM PM to timestamp for timestampdiff in SQL? - sql

I have a generated column that calculates the time difference of time in and time out adding if over time is not empty.
ALTER TABLE tbl_dtr
ADD COLUMN total_worked_hours FLOAT(2) AS (CASE
WHEN time_out = '' then 0
WHEN over_time_out = '' then 0
WHEN time_out <> '' then (TIMESTAMPDIFF(SECOND, time_in, time_out) / 3600)
WHEN over_time_out <> '' then ((TIMESTAMPDIFF(SECOND, time_in, time_out) / 3600) + (TIMESTAMPDIFF(SECOND, over_time_in, over_time_out) / 3600))
END);
The problem here the column total_worked_hours will results null, I don't know how to convert AM/PM to timestamp to calculate timestamdiff.
id
date
time_in
time_out
over_time_in
over_time_out
total_worked_hours
1
2021-08-04
08:35 AM
06:51 PM
07:05 PM
11:58 PM
NULL

My "quick and dirty" solution would be:
SELECT
CASE WHEN SUBSTRING('08:35 AM',7,2)= 'AM'
THEN CONVERT(TIME,SUBSTRING('08:35 AM',1,5))
ELSE DATEADD(HOUR,12,CONVERT(TIME,SUBSTRING('08:35 AM',1,5)) ) END as time
Basically
substring your time column with format '08:35 AM'
Test if is AM or PM
if AM >>>> CONVERT(TIME, Substringed value)
else > >>>> CONVERT(TIME, Substringed value) + 12 hours
Now you can perform your DATEDIFF operations.

Related

Format time using 12 hour notation

I've made an SQL query which shows Date and Time, with Time split into Hours and Minutes.
select convert(varchar(10),[Date],23) as [Date],
datepart(hour, [Time])as Hour, datepart(minute, [Time])as Minutes,
FROM [SQLIOT].[dbo].[ZEPB_CaseLog]
The table shows Hours in 24-hour format.
But I want to have it in 12-hour format instead, with single digits having a '0' prefix.
i.e: 01, 02, 03, etc.
I thought of using case to do it:
select convert(varchar(10),[Date],23) as [Date],
case when
datepart(hour, [Time])> 12 then (datepart(hour, [Time])- 12) as Hour
, datepart(minute, [Time])as Minutes,
FROM [SQLIOT].[dbo].[ZEPB_CaseLog]
Doing so gives me a syntax error on line
datepart(hour, [Time])> 12 then (datepart(hour, [Time])- 12) as Hour
--Incorrect syntax near the keyword 'as'.
I'm not too familiar with doing subtractions in SQL itself. Is there anything else I should add to fix this?
There is a syntax error on case when, try the below.
select convert(varchar(10),[Date],23) as [Date]
, case when datepart(hour, [Time])> 12
then (datepart(hour, [Time])- 12)
else datepart(hour, [Time]) End as Hour
, datepart(minute, [Time])as Minutes,
FROM [SQLIOT].[dbo].[ZEPB_CaseLog]
Given you are interested in formatting, i.e. display, then lets use strings.
declare #Time time = '09:33:44 pm'
select #Time [Original]
, format(cast(#Time as datetime),N'hh') [Format Hour] -- SQL Server 2012 + (format works differently for time and datetime - datetime is required here)
, case when len(convert(varchar(32),#Time,109)) > 17 then convert(varchar(2),#Time,109) else '0' + convert(varchar(1),#Time,109) end [Convert Hour] -- SQL Server pre-2012
-- If you ultimatly want the hours and minutes together then do it as one
, format(cast(#Time as datetime),N'hh\:mm') [Format hour:min] -- SQL Server 2012 + (format works differently for time and datetime - datetime is required here)
, case when len(convert(varchar(32),#Time,109)) > 17 then convert(varchar(5),#Time,109) else '0' + convert(varchar(4),#Time,109) end [Convert hour:min] -- SQL Server pre-2012
-- And if you want am/pm
, format(cast(#Time as datetime),N'hh\:mm tt') [Format hour:min tt] -- SQL Server 2012 + (format works differently for time and datetime - datetime is required here)
, case when len(convert(varchar(32),#Time,109)) > 17 then convert(varchar(5),#Time,109) else '0' + convert(varchar(4),#Time,109) end -- SQL Server pre-2012
+ case when #Time >= '12:00:00' then ' PM' else ' AM' end [Convert hour:min tt] -- SQL Server pre-2012
Returns:
Original Format Hour Convert Hour Format hour:min Convert hour:min Format hour:min tt Convert hour:min tt
21:33:44.0000000 09 09 09:33 09:33 09:33 PM 09:33 PM
If you were interested in adding/subracting dates then use dateadd.

Query Datediff to output HH:MM in SQL Server

I'm working with SQL Server 2012, and I have two columns start and end with varchar(5) values in HH:MM format.
The data looks like this
ID Start End
------------------------
1 00:00 06:00
2 06:00 16:00
3 16:00 18:00
4 18:00 24:00
My query is like this:
SELECT
a.start,
a.[end],
RIGHT('0' + CONVERT(VARCHAR(3), DATEDIFF(MINUTE, a.Start, a.[end]) / 60), 2) + ':' +
RIGHT('0' + CONVERT(VARCHAR(2), DATEDIFF(MINUTE, a.Start, a.[end]) % 60), 2) AS TotalHours
FROM
TransactionActivity a
I exec the query with where clause based on ID number, it gives me the correct result, until in ID 4: i got error like this
Conversion failed when converting date and/or time from character string.
I think it because the End time value is 24:00, how can I make it to get the time difference?
I think you'd be better off converting them into full datetime's (using an arbitrary date) because then the date functions will work correctly.
select
a.[start]
, a.[end]
, RIGHT('0' + CONVERT(varchar(3),DATEDIFF(minute,a.[Start], a.[end])/60),2) + ':' +
RIGHT('0' + CONVERT(varchar(2),DATEDIFF(minute,a.[Start],a.[end])%60),2)
as TotalHours
from (
select id
, case when [Start] = '24:00' then dateadd(minute, 1, convert(datetime, '23:59')) else convert(datetime, [Start]) end [Start]
, case when [End] = '24:00' then dateadd(minute, 1, convert(datetime, '23:59')) else convert(datetime, [End]) end [End]
from TransactionActivity
) a

Query date and specific time in the where clause

I'm looking for some help in Oracle SQL. I need to query date and time in the where clause to find shift data based on current date. There are 3 shifts, 5am to 1pm, 1pm to 9pm and 9pm to 5am(next day morning. For example
SELECT 'T1' AS SHIFT, WORK_CENTER, SUM(CASE WHEN AQL='PASS' THEN 1 ELSE 0) END AS AQL_PASSED
FROM Z_INSPECTION_DEFECTS
WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH:MI:SS '') AND
DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 1:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH:MI:SS '')
I do not get any results from this query. The date time field is a timestamp on local Los Angeles time.
The immediate problem is that you're looking dor times that are after 5am and before 1am, which logically means nothing matches - as no time can fulfil both at once. You can use 24-hour times instead:
WHERE DATE_TIME >= TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), '' 5:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH24:MI:SS '') AND
DATE_TIME < TO_DATE((SELECT CONCAT(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY''), ''13:00:00 '') FROM DUAL) , ''DD-MON-YYYY HH24:MI:SS '')
But there are other ways to get those, e.g. just without the queries against dual:
WHERE DATE_TIME >= TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || '' 5:00:00 '', ''DD-MON-YYYY HH24:MI:SS '') AND
DATE_TIME < TO_DATE(TO_CHAR(CURRENT_DATE, ''DD-MON-YYYY'') || ''13:00:00 '', ''DD-MON-YYYY HH24:MI:SS '')
or with truncation and date arithmetic:
WHERE DATE_TIME >= TRUNC(CURRENT_DATE) + (5/24) AND
DATE_TIME < TRUNC(CURRENT_DATE) + (13/24)
You really need to be getting those times in the target time zone though, e.g.:
WHERE DATE_TIME >= FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), ''America/Los_Angeles'') AND
DATE_TIME < FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), ''America/Los_Angeles'')
You need to be careful with current_date, which is in you current session time zone, and sysdate which is in the server time zone. If your session is UTC then current_date might not give you the day you expect.
(I've stuck with escaped single quotes as that is mostly what you have in the question, implying you're probably running this with dynamic SQL; whether you need to is another matter. If you're only doing that to provide the period offsets at runtime then that wouldn't need to be dynamic...)
You can see the generated times from those calculations with:
select FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (5/24) AS TIMESTAMP), 'America/Los_Angeles'),
FROM_TZ(CAST(TRUNC(CURRENT_DATE) + (13/24) AS TIMESTAMP), 'America/Los_Angeles')
from dual;
FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(5/24)ASTIMESTAM FROM_TZ(CAST(TRUNC(CURRENT_DATE)+(13/24)ASTIMESTA
------------------------------------------------- -------------------------------------------------
2018-10-22 05:00:00.000000000 AMERICA/LOS_ANGELES 2018-10-22 13:00:00.000000000 AMERICA/LOS_ANGELES

Need to format char(4) hhmm to time only or text to look like hh:mm in sql

In the script below, How do I convert the column HHMM to HH:MM and
convert it to 12hr clock?
The column is a char(4) and format 0000 - 2359.
Just want time or text with a colon(:), no date.
Please note that I do not want date or seconds. How do I do this?
Thank you for your help!
Select
th.[store] as 'My Store',
---> this column th.hhmm as Time, (I need this to format hh:mm)
emp.[First Name],
td.Type as [Total],
Count(*) as Qty,
Convert(varchar(50),SUM(Amount1),1) AS Amount
Try this. It uses LEFT and RIGHT functions
declare #time char(4)='2359'
select left(convert(varchar(100),cast(concat(left(#time,2),':',right(#time,2)) as time),9),5)+
' '+
right(convert(varchar(100),cast(concat(left(#time,2),':',right(#time,2)) as time),9),2)
SQL Server:
right('00' + cast((cast(substring(th.hhmm, 1, 2) as int) - 1) % 12 + 1 as varchar(2)), 2) +
':' + substring(th.hhmm, 3, 2) +
case when cast(substring(th.hhmm, 1, 2) as int) >= 12 then 'pm' else 'am' end
You can use substr to do this in Oracle.
select substr(th.hhmm,1,2)||':'||substr(th.hhmm,3,2) from t
In SQL Server, you can use substring
select substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2) from t
Fiddle with sample data
Edit:
select
case when cast(substring(th.hhmm,1,2) as int) < 12 then
case when cast(substring(th.hhmm,1,2) as int) = 0 then
'12'+':'+substring(th.hhmm,3,2)+' AM'
else substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2)+' AM' end
when cast(substring(th.hhmm,1,2) as int) > 12 then
cast(substring(th.hhmm,1,2)%12 as varchar(2)) +':'+substring(th.hhmm,3,2)+' PM'
when cast(substring(th.hhmm,1,2) as int) = 12 then
substring(th.hhmm,1,2)+':'+substring(th.hhmm,3,2)+' PM'
end

How to put datetime condition in where clause on nvarchar column in TSQL?

In SQL server 2005 database, a table has a nvarchar column that contains either datetime or some string value. e.g. 03/11/2011 4:00:07 AM or Completed.
select * from log
where status >=
case isdate(status)
when 1 then convert(datetime, '03/11/2011 12:00:01 AM')
else ''
end
and status <=
case isdate(status)
when 1 then convert(datetime, '03/11/2011 4:00:00 PM')
else ''
end
I need data where status field has datetime and datetime is between date1 and date2.
WHERE
CASE WHEN ISDATE(status) = 1
THEN CONVERT(DATETIME,status)
END BETWEEN '20110311 12:00:01' AND '20110418 16:00:00'