Subtract ISO 8601 timestamps in Oracle - oracle

I want to subtract two timestamps in ISO 8601 format (2021-08-24T12:59:35Z - 2021-08-24T12:59:05Z)
Think the easiest way is convert this timestamp to epoch and then subtract.
Just can't get the syntax right for the conversion.
How do I convert 2021-08-24T12:59:05Z to this : 1629809975 ?

Like the comment says, a lot depends on how you want the result formatted.
If you are ok with an INTERVAL, then the easiest thing to do is use TO_UTC_TIMESTAMP_TZ which actually takes an ISO 8601 formatted string as a parameter:
SELECT TO_UTC_TIMESTAMP_TZ('2021-08-24T12:59:35Z') - TO_UTC_TIMESTAMP_TZ('2021-08-24T12:59:05Z') AS RESULT
FROM DUAL;
Which returns this result:
RESULT
+000000000 00:00:30.000000000
Otherwise, if you want the number of seconds, you can incorporate CAST and ROUND to get the result:
SELECT ROUND((CAST(TO_UTC_TIMESTAMP_TZ('2021-08-24T12:59:35Z') AS DATE) - CAST(TO_UTC_TIMESTAMP_TZ('2021-08-24T12:59:05Z') AS DATE)) * 86400) AS RESULT
FROM DUAL;
RESULT
30
Here is a DBFiddle showing both options (DBFiddle)

Related

Convert difference of dates to date with timestamp

How to convert the difference of 2 dates with a timestamp to date with timestamp again, Oracle giving number but i want to compare timestamp.
select emp_date>to_date(sysdate,'yyyy-MM-dd HH24:MI:SS')-todate('2021-03-22 10:20:12') from emp;
above query giving error: expected date but got NUMBER.
Thanks in advance
What you are saying makes no sense. Difference of two DATE datatype values is number of days between them. For example
SQL> select sysdate - to_date('21.03.2021 13:12', 'dd.mm.yyyy hh24:mi') diff from dual;
DIFF
----------
,943217593
SQL>
You CAN convert it to a prettier format (days, hours, minutes, seconds), but it is still a NUMBER, it is not a date.
Therefore, you can't compare EMP_DATE (which is a DATE datatype column, isn't it?) to a number as it just doesn't make sense.
Is 22nd of March 2021 larger or smaller than 0.94? It's neither.
[TL;DR] You cannot as your data types do not match and it does not make sense to compare a date/time value to an interval.
If you do:
date_value1 - date_value2
You will get a NUMBER data type representing the number of (fractional) days between the two date values.
You can explicitly cast the subtraction operation to get an INTERVAL DAY TO SECOND data type using:
(date_value1 - date_value2) DAY TO SECOND
So, for your code that would be:
SELECT emp_date > ( sysdate - TO_DATE( '2021-03-22 10:20:12', 'YYYY-MM-DD HH24:MI:SS' ) ) DAY TO SECOND
FROM emp;
However, that will fail as you cannot compare a DATE to an INTERVAL DAY TO SECOND and SQL does not have a boolean data type so > does not make sense.
To fix that later point you could use a CASE expression but the difference in data types is a show-stopper as you can't compare a date to an interval.
but i want to compare timestamp.
You don't have a TIMESTAMP data type, you have either a number (representing an interval in days) or an INTERVAL data type. If you want to convert it back to a DATE or TIMESTAMP then you need to add your interval to an epoch value.

How to make a constraint on DATE FORMAT in ORACLE

say my usual Date format is '14-jan-2019' and i want my date to only be accepted as 'YYYY-MM-DD' how do i do that? and can i change jan to an actual number?
In my opinion, the right / correct way to do that is to declare your date column (or variable or whatever it is) as DATE, e.g.
create table test (date_column date);
or
declare
l_date_variable date;
begin
...
Doing so, you'd let the database take care about valid values.
You'd then be able to enter data any way you want, using any valid date format mask, e.g.
to_date('06.01.2020', 'dd.mm.yyyy')
date '2020-01-06'
to_date('2020-06-01', 'yyyy-dd-mm')
etc. - all those values would be valid.
A DATE data type has no format - it is stored internally as 7-bytes representing year (2 bytes) and month, day, hour, minute and second (1 byte each).
'14-JAN-2019' is not a date - it is a text literal.
If you want to store date values then use a DATE data type.
If you want to only accept strings of a specific format as input then in whatever user interface you use to talk to the database then accept only that format. If you are converting strings to DATEs and wanting an exact format then you can use:
TO_DATE( '2019-01-14', 'fxYYYY-MM-DD' )
Note: the fx format model will mean that the exact format is expected and the typical string-to-date conversion rules will not be applied.

Oracle - Date Format

I need your assistance with converting Oracle dates.
I have a column that stores dates like this 20150731 00:00:34.220. However, I would like to show the column like this 20150731 but when I run a simple select statement to test output I get the following error.
select TO_DATE('20150731 00:00:34.550','YYYYMMDD')
from dual
Error
ORA-01830: date format picture ends before converting entire input string
This query
select TO_DATE('20150731 00:00:34.550','YYYYMMDD')
from dual
leads to error
ORA-01830: date format picture ends before converting entire input string
because you pass string with length 22 characters, but at the same time you pass date format with 8 characters, which obviously doesn't correspond to string. You should write the query as
select to_timestamp('20150731 00:00:34.550','yyyymmdd hh24:mi:ss.ff3')
from dual
As for your table, since you have varchar2 column with dates, you have to take care about table content. Query requires exect matching of the source string and date format.
If you want to show only date without time and you don't need to process this string as date, you can make just
select substr('20150731 00:00:34.550', 1, 8)
from dual
What is the data type of the column? If it is DATE (as it should be) then not it is not stored in the format you say. It is stored in an internal binary format. You would/should use the to_char function to DISPLAY it in whatever format you choose. If you do not use the to_char function, it will be displayed in the format specified by NLS_DATE_FORMAT, which can be specified at several locations.
As for your example, you passed a string format of yyyymmd hh:mi:ss.fff', but you provided a description mask of only YYYYMMDD. It doesn't know what to do with time component. In addition to that when you SELECT TO_DATE, oracle also has to do an implied TO_CHAR to convert it back to a string for display purposes.
In addition, you provided your to_date with a character string that included fractions of seconds. A DATE data type only resolves to seconds. If you need fractional seconds, you need to use TIMESTAMP, not DATE.
If your column is a varchar and you need a date output:
select TO_DATE(substr('20150731 00:00:34.550', 1, 8),'YYYYMMDD') from dual
If it's in a date format and you need a string output:
select to_char(your_column, 'YYYYMMDD') from your_table
Is that being stored in an Oracle datetime column? If not, you may have to do some manipulation to get it into a DD-MON-YYYY format. If it is being stored as a text string you could use SUBSTR( Date_field, Start_Position, Length) to get the first 8 characters. check out this link SUBSTR
Working on the assumption that you're not trying to change the value in the column, and are just trying to show it in the YYYYMMDD format -
As mentioned by a_horse_with_no_name, you'll just need to convert it to a character string. In this example I used systimestamp as my date:
SELECT TO_CHAR(systimestamp,'YYYYMMDD') FROM DUAL
Result:
20160121
That should give you the YYYYMMDD format you want to display.

Converting XML date (ISO-8601) into timestamp in Oracle

Could you please help me in converting date time of format from "2015-02-23T16:26:41.485+05:30" to "23-FEB-15 16.26.41.000000000 AM" in Oracle.
I have an ISO-8601 date string in variable:
START_TIME='2015-02-23T16:26:41.485+05:30'
When I use
to_timestamp(START_TIME,'yyyy-mm-dd"T"hh24:mi:ss.ff3')
I get:
Error report:
ORA-01830: date format picture ends before converting entire input string
ORA-06512: at line 55
01830. 00000 - "date format picture ends before converting entire input string"
*Cause:
*Action:
To convert your string to a timestamp with time zone value, you need the to_timestamp_tz() function:
select to_timestamp_tz('2015-02-23T16:26:41.485+05:30',
'yyyy-mm-dd"T"hh24:mi:ss.ff3tzh:tzm') as result
from dual;
RESULT
-----------------------------------
2015-02-23 16:26:41.485000 +05:30
This includes the TZH and TZM datetime format model elements to handle the time zone offset; those can't be used in to_timestamp() or to_date() as those data types don't understand time zones.
You seem to want to lose the fractional seconds part, and the time zone information; you can achieve both at once by casting to a timestamp (without timezone) with the fractional seconds precision set to zero:
select cast(to_timestamp_tz('2015-02-23T16:26:41.485+05:30',
'yyyy-mm-dd"T"hh24:mi:ss.ff3tzh:tzm') as timestamp(0)) as result
from dual;
RESULT
-----------------------------------
2015-02-23 16:26:41.000000
But losing the time zone seems dangerous, unless you are sure that the data you receive is always going to be in the same time zone as your database. If you might have different time zones in the data but for some reason don't want to retain that information, you can also convert to a specific time zone for storage, but it isn't clear whether you need or want that here. If you aren't keeping the time zone or the fractional seconds, you may be better off with a date anyway.
Dates and timestamps do not have any inherent format within the database. If you then want to see that converted back into a string in the format you specified, pass it back into a to_char() call with the formatting you want; but as your example has both a 24-hour-clock hour value and an (incorrect) AM/PM indicator that isn't clear either. Maybe you want:
select to_char(cast(to_timestamp_tz('2015-02-23T16:26:41.485+05:30',
'yyyy-mm-dd"T"hh24:mi:ss.ff3tzh:tzm') as timestamp(0)),
'dd-MON-rr hh:mi:ss.ff9 am') as result
from dual;
RESULT
-----------------------------------
23-FEB-15 04:26:41.000000000 PM
To store the value from your START_TIME variable in a timestamp column the approach is exactly the same, just use that instead of the fixed value I've used above to demonstrate the conversion:
cast(to_timestamp_tz(START_TIME, 'yyyy-mm-dd"T"hh24:mi:ss.ff3tzh:tzm')
as timestamp(0))

Date as number in sql

When we type current date in Excel cell as 08-May-2013
Right click on the cell and in the format when i click number as category i get a number
Date-08-May-13
Formatted one-41402.00
So is there anyway i can get the same number in sql
I tried using this.
select to_char(sysdate,'J') from dual
But the output is 2456421
I understand that this is a Julian value
But can anyone help me in getting the output as that i am getting on excel i.e; 41402
The Windows version of Excel stores dates as serial numbers. 01-Jan-1900 is 1, 02-Jan-1900 is 2, etc. The Mac version used to use a different starting date; I don't know whether that's still the case.
The essential data you need is in simple date arithmetic.
select current_date, current_date - date '1900-01-01'
from dual;
That returns 41400.67037037037 for my current connection. Rounding up and adding 1 for fenceposting would return the number you're looking for, but I'd want to test that with multiple time zones and such before I'd swear by it.
A date in Excel is stored as a serial number, with 01-JAN-1900 as 1. Citation.
We can do arithmetic with dates in Oracle, so converting to an Excel date from Oracle would be:
trunc(sysdate) - to_date( '1900-01-01', 'yyyy-mm-dd')
I've tested this and infuriatingly it produces 41401 - because it's going from midnight. So obviously Microsoft are using a ceiling function to raise it to the next integer:
ceil (sysdate - to_date( '1900-01-01', 'yyyy-mm-dd') )

Resources