Convert Date strored as number(32,0) in oracle - oracle

I have an issue importing date from a Tririga database into a SQL database. Mainly I cant convert the date properly and it looks like is not the commont format I have seen around.
Eg date value incomming 775724400000
Running something like select to_date('765187200000', 'DDMMYYYYHH24MISS') my_date FROM dual;
give me an error
ORA-01847: day of month must be between 1 and last day of month
01847. 00000 - "day of month must be between 1 and last day of month"
I found the following info from this link seems to be also from tririga
link_help
And the size of the number are about 10 digits meanwhile this one is 12 and I know for fact this dates should be from the past 10 years (most of them)
I can't seem to find anything that gives me an answer how to convert this into proper dates.
Any suggestions?

The input number appears to be "epoch", a count of milliseconds elapsed since 1 January 1970 GMT (UTC).
To convert to date is not difficult:
select date '1970-01-01' + (775724400000 / 86400000) as dt from dual;
DT
--------------------
1994-Aug-01 07:00:00
Note the hard-coded literals: date '1970-01-01' (epoch is by definition measured from midnight on this date) and 86400000. By one of the definitions (in the previous version of the International System of Units and Weights), a second is 1/86400 of a median day. In Oracle, date arithmetic is based on the number 1 representing one day, so to convert your milliseconds to days you must divide your input by 86400 * 1000.
The most delicate question has to do with time zones (and possibly daylight saving time, also related to time zone). In most cases, epoch is measured from midnight on 1 January 1970 GMT, not from midnight on 1 January 1970 in local time. Do you need to adjust for that? Only you and your business users can answer that question.
(As an aside, the number you provided does NOT represent a date in the past 10 years - not even close.)

Related

Obtain count to MI:SSSS precision?

TRANSACTION_DATE is a DATE data type.
This code lists all of the event dates to the MI:SSSS.
select to_char(transaction_date,'YYYY-MON-DD HH24:MI:SSSS') as trans_date from ticket_orders;
Now I want to get counts for those dates and I get ORA-00979 not a GROUP BY function.
select to_char(transaction_date,'YYYY-MON-DD HH24:MI:SSSS') as trans_date,
count(*)
from ticket_orders
group by to_char(transaction_date,'YYYY-MON-DD HH24:MI:SSSS');
ERROR ORA-00979: not a GROUP BY expression
How do I get a count of transactions to the MI:SSSS precision?
A DATE data type is a binary data type that is composed of 7 bytes representing century, year-of-century, month, day, hour, minute and second. It ALWAYS has those components and it NEVER contains fractional seconds (that is for the TIMESTAMP data type which can have fractional seconds and/or time zone information).
If DATE type does not store fractional seconds, why does a typical row from my first query look like this 2021-FEB-25 07:58:2626
That is because you are displaying the seconds twice as you use the SS format model for seconds twice.
Your query can just be:
select to_char(transaction_date,'YYYY-MON-DD HH24:MI:SS') as trans_date,
count(*)
from ticket_orders
group by
transaction_date;
db<>fiddle here
The DATE data type does not store fractional seconds. You can reference the Oracle documentation about data types.
DATE
Valid date range from January 1, 4712 BC, to December 31, 9999 AD. The
default format is determined explicitly by the NLS_DATE_FORMAT
parameter or implicitly by the NLS_TERRITORY parameter. The size is
fixed at 7 bytes. This data type contains the datetime fields YEAR,
MONTH, DAY, HOUR, MINUTE, and SECOND. It does not have fractional
seconds or a time zone.
If you want a data type that stores fractional seconds you will need to use TIMESTAMP
TIMESTAMP [(fractional_seconds_precision)]
Year, month, and day values of date, as well as hour, minute, and
second values of time, where fractional_seconds_precision is the
number of digits in the fractional part of the SECOND datetime field.
Accepted values of fractional_seconds_precision are 0 to 9. The
default is 6. The default format is determined explicitly by the
NLS_TIMESTAMP_FORMAT parameter or implicitly by the NLS_TERRITORY
parameter. The size is 7 or 11 bytes, depending on the precision. This
data type contains the datetime fields YEAR, MONTH, DAY, HOUR, MINUTE,
and SECOND. It contains fractional seconds but does not have a time
zone.

Determine if spring or fall and adjust time if DST or not

I have a query like this:
SELECT
to_date(to_char((from_tz(to_timestamp(to_char(my_column, 'YYYY-MM-DD HH:MI:SS PM'), 'YYYY-MM-DD HH:MI:SS PM') ,'America/Edmonton')at time zone 'America/Vancouver'),'YYYY-MM-DD'),'YYYY-MM-DD') as Date_Column
FROM
my_table
It converts the time between MST to PST. This works most of the time except when daylight savings time occurs. Then a situation happens when in the clock moves forward an hour, and then since an hour is lost (for example 1:59 to the 3:00 am) then we are trying to convert a fictional time.
So I am aware of the issue, and I know Oracle will throw this error for that reason:
ORA-01878: specified field not found in datetime or interval
I've looked all over the Internet for a possible work around but can't really find anything that works. I just want to modify my query so that it can tell what time of year it is and either do the conversation when the time exists, or handle the time somehow when it does not exists. Perhaps add the extra hour when it's missing, and remove it when it's the other time of year.
Does anyone have a solution for this? Is this an impossible problem?
Instead of all the conversions you are using, just use AT TIME ZONE. You may need to take extra care depending on the data type of your column. The AT TIME ZONE functionality will always take into account daylights savings time.
If your column is a TIMESTAMP WITH TIME ZONE, that would be ideal
because you could just say AT TIME ZONE 'PST' and you would get the
time in PST.
If the column is the datatype TIMESTAMP, when you use AT TIME ZONE it
will convert from the time zone of the current session to whatever
you specify.
If your column is a DATE, you will need to convert it to a TIMESTAMP first, then you can use the AT TIME ZONE function. Converting the DATE to TIMESTAMP will make the time zone 0:00 offset so be sure to account for that.
Another handy trick is to use AT LOCAL. This will convert the timestamp to the time zone of the current session. This may be handy if you have users of your application that are in multiple time zones.
Example
I am in the time zone -04:00 (East coast US) which is why that appears as my time zone in the examples below.
WITH
my_table
AS
(SELECT TIMESTAMP '2021-01-01 8:00:00 -7:00' AS ts_with_tz,
TIMESTAMP '2021-01-01 8:00:00' AS ts,
DATE '2021-01-01' + (8 / 24) AS dt
FROM DUAL)
SELECT 1 AS example_num,
t.ts_with_tz,
t.ts,
t.dt
FROM my_table t
UNION ALL
SELECT 2 AS example_num,
t.ts_with_tz AT TIME ZONE 'PST',
t.ts AT TIME ZONE 'PST',
TO_TIMESTAMP (t.dt) AT TIME ZONE 'PST'
FROM my_table t
ORDER BY 1;
RESULT
EXAMPLE_NUM TS_WITH_TZ TS DT
______________ ______________________________________________________ ______________________________________________________ ______________________________________________________
1 01-JAN-21 08.00.00.000000000 AM -07:00 01-JAN-21 08.00.00.000000000 AM AMERICA/NEW_YORK 01-JAN-21 08.00.00.000000000 AM AMERICA/NEW_YORK
2 01-JAN-21 07.00.00.000000000 AM AMERICA/LOS_ANGELES 01-JAN-21 05.00.00.000000000 AM AMERICA/LOS_ANGELES 31-DEC-20 09.00.00.000000000 PM AMERICA/LOS_ANGELES

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.

convert date to order day of the month

How can I convert date to the order day of the month in ORACLE?
Ex: 31/07/2000 -> "Monday, the Thirty-First of July, 2000".
Is there any format date which can solve this problem?
Thanks so much!
Yes, there is - you need to combine some format elements (and modifiers) with a bit of boilerplate text (to add "the" and "of"). Like this:
select to_char( to_date('31/07/2000', 'dd/mm/yyyy')
, 'fmDay, "the " Ddspth "of" Month, yyyy') as spelled_out_date
from dual;
SPELLED_OUT_DATE
---------------------------------------
Monday, the Thirty-First of July, 2000
Note that, while the names of days of the week and calendar months depend on your session's then-current NLS_DATE_LANGUAGE, the Ddspth element will always be in English. So, alas, this solution DOES NOT WORK for other languages.

months_between for a leap year

When I find months between 28-FEB-11 and 29-FEB-12, months_between function in oracle returns 12. Actually it should be 12.096. This function is not calculating for the leap year proper.
For between 28-FEB-11 and 29-FEB-12, it is 1 year(12 months) and 1 day.
select months_between('28-FEB-12', '28-FEB-11') from dual; -- 12
**select months_between('29-FEB-12', '28-FEB-11') from dual; -- 12**
select months_between('28-FEB-12', '27-FEB-11') from dual; -- 12.0322
select months_between('27-FEB-12', '28-FEB-11') from dual; -- 11.9677
is this an Oracle bug??..
-Vishwa
From the Oracle documentation:
MONTHS_BETWEEN returns number of months between dates date1 and date2. If date1 is later than date2, then the result is positive. If date1 is earlier than date2, then the result is negative. If date1 and date2 are either the same days of the month or both last days of months, then the result is always an integer. Otherwise Oracle Database calculates the fractional portion of the result based on a 31-day month and considers the difference in time components date1 and date2.
So it's following the documented behavior. It's just not what you expected.
It's not a bug because ORACLE says so, it's a logical error driven by a human (and documenting as something rigth) which is worse.
How come if difference between the last days of January and February months is exactly 1 month (29 exact days). Please see below:
MONTHS_BETWEEN('29-FEB-12','31-JAN-12')
1
With an extra day (30 days) the difference in months is less than 1. Please see below:
MONTHS_BETWEEN('29-FEB-12','30-JAN-12')
.967741935
WRONG. That's not rigth at all!
SQL Server in another hand handle this correctly:
select DATEDIFF(MM,'29-FEB-12','30-JAN-12')
select DATEDIFF(MM,'29-FEB-12','31-JAN-12')
both are 1

Resources