ORA-01849: hour must be between 1 and 12 - oracle

WHERE (ResTRRequest.RequestTime BETWEEN TO_CHAR(TRUNC(TO_DATE('2012-12-01 20:10:10', 'HH')), 'YYYY-MM-DD HH24:MI:SS')
AND TO_CHAR(TRUNC(CURRENT_TIMESTAMP, 'HH') + INTERVAL '59:59' MINUTE TO SECOND, 'YYYY-MM-DD HH24:MI:SS'))
I have above where condition in query when i execute it,it gives me hours must be between 1 to 12 due to static date I have given i.e ''2012-12-01 20:10:10', 'HH')' if I put sysdate the its working fine but due to static date it gives me error.

Let's break this down a bit:
WHERE (ResTRRequest.RequestTime
BETWEEN TO_CHAR(TRUNC(TO_DATE('2012-12-01 20:10:10', 'HH')), 'YYYY-MM-DD HH24:MI:SS')
AND TO_CHAR(TRUNC(CURRENT_TIMESTAMP, 'HH') + INTERVAL '59:59' MINUTE TO SECOND, 'YYYY-MM-DD HH24:MI:SS'))
In the first place, I don't think you mean this: TRUNC(TO_DATE('2012-12-01 20:10:10', 'HH')), I think maybe you mean this: TRUNC(TO_DATE('2012-12-01 20:10:10'), 'HH'). The number from 1-12 error comes from the fact that you have an hour of 20 and are trying to convert it into a date with the mask of HH. But as I said I think that's a typo. You can also use a TIMESTAMP literal here rather than TO_DATE():
TRUNC(TIMESTAMP'2012-12-01 20:10:10', 'HH')
Second, and just to get this out of the way, are you storing dates or timestamps as strings? That's not a good idea.
Third, it's not a good idea to use BETWEEN in date comparisons because you can miss the edge cases. It might be better to rewrite this as follows:
WHERE ( ResTRRequest.RequestTime >= TO_CHAR(TRUNC(TO_DATE('2012-12-01 20:10:10'), 'HH'), 'YYYY-MM-DD HH24:MI:SS')
AND ResTRRequest.RequestTime < TO_CHAR(TRUNC(CURRENT_TIMESTAMP, 'HH') + INTERVAL '1' HOUR, 'YYYY-MM-DD HH24:MI:SS') )

Problem is in mask:
TO_DATE('2012-12-01 20:10:10', 'HH')
Replace with this one:
TO_DATE('2012-12-01 20:10:10', 'HH24')

Assuming that ResTRRequest.RequestTime is of a date type, this Where clause will work:
where ResTRRequest.RequestTime
BETWEEN TRUNC(TO_DATE('2015-02-26 20:10:10', 'YYYY-MM-DD HH24:MI:SS'), 'HH')
AND TRUNC(CURRENT_TIMESTAMP, 'HH') + INTERVAL '59:59' MINUTE TO SECOND
If you have to compare character representations, keep in mind that you compare in lexicographic order, meaning that prefixes of strings are sorted before their strings! Avoid ensueing complications by using identical formatting models with componnents arranged in the order of decreasing significance. E.g.
TO_CHAR(<whatever>, 'YYYY-MM-DD HH24:MI:SS')
but not
TO_CHAR(<whatever>, 'MM/DD/YYYY HH24:MI:SS')

If the language setting on Oracle is set for using the 12 hours time, this problem will occur when converting the 24 hours time format.
There are two solutions to this :
Convert TIMESTAMP/DATE format in Oracle client
alter session set nls_timestamp_format='YYYY-MM-DD HH24:MI:SS.FF6';
Convert query to match 24hr format
SELECT * FROM TEST_ WHERE DOB > TRUNC(TIMESTAMP'1970-01-01 20:10:10', 'HH');
or
SELECT * FROM TEST_ WHERE DOB > to_date('1970-01-01 20:00:00','YYYY-MM-DD HH24:MI:SS');

One more thing to watch out for in the case you get this error is the data itself.
I've had date stored in xml tag that I had to parse and convert with TO_DATE with this format specifier 'MM/dd/YYYY HH:MI:SS AM'. SQL broke with "ORA-01849: hour must be between 1 and 12" because some records were written like this: "12/20/2017 16:45:00 PM". Pay attention to 16h and PM specfier...

Related

How do I separate the time and date in SQL navigator?

I am trying to separate the time and date in one column to be independent off each other. I am new at writing scripts
this is my query:
select
*
from
[tablename]
where
to_date([column_name]) in ( '15-Jun-2021', '16-Jun-2021' )
and
to_char([column_name],'dd-Mon-yyyy HH:MM:ss') < '15-Jun-2021 19:54:30'
The way you put it, it would be
select *
from your_table
where date_column >= date '2021-06-15'
and date_column < to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss')
because
date_column should be of date datatype. If it isn't, you'll have problems of many kinds in the future. Therefore,
don't to_date it, it is already a date
don't to_char it either, because you'd be comparing strings and get unexpected result. Use that function when you want to nicely display the result
the second condition you wrote makes the first one questionable. If date_column is less than value you wrote, then you can omit date '2021-06-16' from the first condition because you won't get any rows for that date anyway
date literal (date '2021-06-15') sets time to midnight, so condition I wrote should return rows you want
SQL> select date '2021-06-15' first,
2 to_date('15.06.2021 19:54:30', 'dd.mm.yyyy hh24:mi:ss') second
3 from dual;
FIRST SECOND
------------------- -------------------
15.06.2021 00:00:00 15.06.2021 19:54:30
SQL>

Difference between two dates and getting result in timestamp

I´m trying to calculate the difference between two dates in Oracle and getting the result as a TimeStamp. This is the easiest thing to do in SQL Server, but it seems that Oracle does not have a easy way to solve this. I refuse to believe that I have to write that much code to get what I need. Can someone tell me if there is a easier way to get that difference?:
SELECT TO_CHAR(EXTRACT(HOUR FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
|| ':' ||
TO_CHAR(EXTRACT(MINUTE FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
|| ':' ||
TO_CHAR(EXTRACT(SECOND FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00')
I need the result be something like:
enddate = '2017-03-01 17:30:00'
startdate = '2017-03-01 10:00:00'
difference: 07:30:00
Substract the two dates. Add the result to the current date (without any time component, trunc(sysdate)) and show only the time.
select to_char(trunc(sysdate) + (to_date('2017-03-01 17:30:00', 'YYYY-MM-DD HH24:MI:SS') -
to_date('2017-03-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'))
,'HH24:MI:SS')
from dual

Converting NUMBER variable to Datetime stamp

I am using the following, where I am converting NUMBER variable to Datetime stamp.
to_char(
(to_timestamp('01-JAN-1970 00:00:00','DD-MON-YYYY HH24:MI:SS') +
(END_SAMPLE_TS_5MIN_MS/(1000*60*60*24)),'DD-MON-YYYY HH24:MI:SS')
But I notice the output resulting from above is behind by 1 second from actual value.
Say for example if END_SAMPLE_TS_5MIN_MS=1388984699999.
Instead of showing : 06Jan2014 05:04:59
It is showing it as 06Jan2014 05:05:00
The milliseconds are rounded to nearest second.
Please help!
You can use numtodsinterval, something like:
select to_timestamp('01-JAN-1970 00:00:00.000','DD-MON-YYYY HH24:MI:SS.FF3') +
numtodsinterval(1388984699.999, 'SECOND')
from dual;
Output:
1/6/2014 5:04:59.999000000 AM
Hope that helps
If you're not interested in utilizing the milliseconds to round up, you can effectively take the "floor" of your epoch with a substring:
select to_char((to_timestamp('01-JAN-1970 00:00:00','DD-MON-YYYY HH24:MI:SS')+(substr(1388984699999,1,length(1388984699999)-3)/(60*60*24))),'DD-MON-YYYY HH24:MI:SS')
from dual
We're really just taking the substring of our string minus the last 3 digits (milliseconds in this unix timestamp format) and then adding it to the epoch to get your time.

Oracle current_timestamp to seconds conversion

We are using Oracle database.
In our table timestamp is stored as seconds since 1970, how can I convert the time stamp obtained through current_timestamp() function to seconds
This would do it:
select round((cast(current_timestamp as date) - date '1970-01-01')*24*60*60) from dual
Though I wouldn't use current_timestamp if I was only interested in seconds, I would use SYSDATE:
select round((SYSDATE - date '1970-01-01')*24*60*60) from dual
Maybe not completely relevant. I had to resolve other way around problem (e.g. Oracle stores timestamp in V$RMAN_STATUS and V$RMAN_OUTPUT) and I had to convert that to date/timestamp. I was surprised, but the magic date is not 1970-01-01 there, but 1987-07-07. I looked at Oracle's history and the closest date I can think of is when they ported Oracle products to UNIX. Is this right?
Here's my SQL
SELECT /*+ rule */
to_char(min(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON-YYYY HH24:MI:SS') start_tm
, to_char(to_char(max(stamp)/(24*60*60) + date '1987-07-07', 'DD-MON HH24:MI:SS')) end_tm
FROM V$RMAN_STATUS
START WITH (RECID, STAMP) =
(SELECT MAX(session_recid),MAX(session_stamp) FROM V$RMAN_OUTPUT)
CONNECT BY PRIOR RECID = parent_recid ;
I needed to send timestamp to GrayLog via GELF from Oracle DB. I tried different versions and solutions but only one worked correctly.
SQL:
SELECT REPLACE((CAST(dat AS DATE) - TO_DATE('19700101', 'YYYYMMDD')) * 86400 + MOD(EXTRACT(SECOND FROM dat), 1), ',', '.') AS millis
FROM (SELECT SYSTIMESTAMP AT TIME ZONE 'GMT' AS dat FROM dual)
The result for Systmiestamp
2018/12/18 19:47:29,080988 +02:00
will be
1545155249.080988

Oracle: how to add minutes to a timestamp?

I need to add 30 minutes to values in a Oracle date column. I do this in my SELECT statement by specifying
to_char(date_and_time + (.000694 * 31)
which works fine most of the time. But not when the time is on the AM/PM border. For example, adding 30 minutes to 12:30 [which is PM] returns 1:00 which is AM. The answer I expect is 13:00. What's the correct way to do this?
In addition to being able to add a number of days to a date, you can use interval data types assuming you are on Oracle 9i or later, which can be somewhat easier to read,
SQL> ed
Wrote file afiedt.buf
SELECT sysdate, sysdate + interval '30' minute FROM dual
SQL> /
SYSDATE SYSDATE+INTERVAL'30'
-------------------- --------------------
02-NOV-2008 16:21:40 02-NOV-2008 16:51:40
All of the other answers are basically right but I don't think anyone's directly answered your original question.
Assuming that "date_and_time" in your example is a column with type DATE or TIMESTAMP, I think you just need to change this:
to_char(date_and_time + (.000694 * 31))
to this:
to_char(date_and_time + (.000694 * 31), 'DD-MON-YYYY HH24:MI')
It sounds like your default date format uses the "HH" code for the hour, not "HH24".
Also, I think your constant term is both confusing and imprecise. I guess what you did is calculate that (.000694) is about the value of a minute, and you are multiplying it by the number of minutes you want to add (31 in the example, although you said 30 in the text).
I would also start with a day and divide it into the units you want within your code. In this case, (1/48) would be 30 minutes; or if you wanted to break it up for clarity, you could write ( (1/24) * (1/2) ).
This would avoid rounding errors (except for those inherent in floating point which should be meaningless here) and is clearer, at least to me.
UPDATE "TABLE"
SET DATE_FIELD = CURRENT_TIMESTAMP + interval '48' minute
WHERE (...)
Where interval is one of
YEAR
MONTH
DAY
HOUR
MINUTE
SECOND
from http://www.orafaq.com/faq/how_does_one_add_a_day_hour_minute_second_to_a_date_value
The SYSDATE pseudo-column shows the current system date and time. Adding 1 to SYSDATE will advance the date by 1 day. Use fractions to add hours, minutes or seconds to the date
SQL> select sysdate, sysdate+1/24, sysdate +1/1440, sysdate + 1/86400 from dual;
SYSDATE SYSDATE+1/24 SYSDATE+1/1440 SYSDATE+1/86400
-------------------- -------------------- -------------------- --------------------
03-Jul-2002 08:32:12 03-Jul-2002 09:32:12 03-Jul-2002 08:33:12 03-Jul-2002 08:32:13
I prefer using an interval literal for this, because interval '30' minute or interval '5' second is a lot easier to read then 30 / (24 * 60) or 5 / (24 * 60 * 69)
e.g.
some_date + interval '2' hour
some_date + interval '30' minute
some_date + interval '5' second
some_date + interval '2' day
You can also combine several units into one expression:
some_date + interval '2 3:06' day to minute
Adds 2 days, 3 hours and 6 minutes to the date value
The above is also standard SQL and also works in several other DBMS.
More details in the manual: https://docs.oracle.com/database/121/SQLRF/sql_elements003.htm#SQLRF00221
If the data type of the field is date or timestamp, Oracle should always give the correct result if you add the correct number given in number of days (or a the correct fraction of a day in your case). So if you are trying to bump the value in 30 minutes, you should use :
select field + 0.5/24 from table;
Based on the information you provided, I believe this is what you tried to do and I am quite sure it works.
Can we not use this
SELECT date_and_time + INTERVAL '20:00' MINUTE TO SECOND FROM dual;
I am new to this domain.
like that very easily
i added 10 minutes to system date and always in preference use the Db server functions not custom one .
select to_char(sysdate + NUMTODSINTERVAL(10,'MINUTE'),'DD/MM/YYYY HH24:MI:SS') from dual;
Be sure that Oracle understands that the starting time is PM, and to specify the HH24 format mask for the final output.
SELECT to_char((to_date('12:40 PM', 'HH:MI AM') + (1/24/60) * 30), 'HH24:MI') as time
FROM dual
TIME
---------
13:10
Note: the 'AM' in the HH:MI is just the placeholder for the AM/PM meridian indicator. Could be also 'PM'
Oracle now has new built in functions to do this:
select systimestamp START_TIME, systimestamp + NUMTODSINTERVAL(30, 'minute') end_time from dual
Based on what you're asking for, you want the HH24:MI format for to_char.
To edit Date in oracle you can try
select to_char(<columnName> + 5 / 24 + 30 / (24 * 60),
'DD/MM/RRRR hh:mi AM') AS <logicalName> from <tableName>
SELECT to_char(sysdate + (1/24/60) * 30, 'dd/mm/yy HH24:MI am') from dual;
simply you can use this with various date format....

Resources