String to date conversion in query - sql

i have the following "timestamp" in the column
Mon Aug 10 12:24:46 CDT 2016
so to convert into date, i am doing the following.
select * from
(select TO_DATE(SUBSTR(t.timestamp,9,2) || '-' || SUBSTR(t.timestamp,5,3) ||
'-' || SUBSTR(t.timestamp,27,2), 'DD-MON-YY') from table t where
t.LENGTH(TRIM(t.timestamp)) = 28 as date) where date <= sysdate;
The reason for doing that is, "Oracle sysdate" is returning a current date in the following format
20-SEP-16
So to compare the oracle sysdate, i am using the above approach.
is there any better approach for doing this, i knew this is inefficient using a group of sub-strings inside a select statement and since my "time stamp" value is too long, i am unable to convert to ORACLE date.
I am using oracle 11 as my Database. any help is appreciated.

Here is a proof of concept, assuming the so-called "timestamp" is in fact a string. If it is a proper timestamp with time zone (as it should be), then it's even simpler, you can compare to a date directly.
Note two things: In my mapping I don't have "CDT" for some reason but I do have the standard time zone, CST. I am probably missing a daylight savings time file which I don't care to hunt down and install. And Aug-10-2016 was a Wednesday; Monday won't work, you can't fool Oracle. Wonder why you didn't bother to use an actual, correct date (including the correct day of the week).
Edit: Actually I am not missing any "time zone codes file"; instead, to recognize CDT as a valid time zone, the TZR component in the model below needs to be changed to TZD.
PROOF OF CONCEPT:
select 'x' as col1
from dual
where to_timestamp_tz('Wed Aug 10 12:24:46 CST 2016',
'Dy Mon dd hh24:mi:ss TZR yyyy') <= sysdate
;
COL1
-----
x
1 row selected.

The as date is in the wrong place.
'Aug' is a month name abbreviation in a certain language. Specify that language in to_char to make sure it works independent of your current setting.
Don't only use YY when you have YYYY available.
At last there is the time zone 'CDT'. Is it always 'CDT' or can it be something else? If you need to get from one time zone to another, you'd have to convert to timestamp with timezone first, then move to the other timezone, then convert to date.
Here is the query:
select *
from
(
select
cast(from_tz(cast("date" as timestamp), zone) at time zone 'CDT' as date) as "date"
from
(
select to_date(substr(t.timestamp,9,2) || '-' ||
substr(t.timestamp,5,3) || '-' ||
substr(t.timestamp,25,4),
'DD-MON-YY',
'NLS_DATE_LANGUAGE=AMERICAN') as "date",
substr(t.timestamp,21,3) as zone
from table t
where t.length(trim(t.timestamp)) = 28
)
)
where "date" <= sysdate;
Despite its name from_tz doesn't convert from a timezone, but from a timestamp without timezone to a timestamp with timezone. So we use this to put our timezone information in. timestamp at time zone 'xyz' on the other hand moves the timezone to the one specified (the one we interprete our dates to reside in). cast is used to get from date to timestamp and vice versa.

You can use TO_CHAR function to extract date formate
https://docs.oracle.com/database/121/SQLRF/functions216.htm

Related

Casting Local Time to UTC Formating Incorrect

HIRE_DATE is in a 'DATE' column. The timestamp is local (Los Angeles); I would like to convert it to UTC.
I can't for the life of me fathom why the UTC output is mangled (Last 2 digits of YY is the DD; and vice-versa) -- and the time does not convert to UTC.
HIRE_DATE: 30/04/2019 12:00:00 AM
select from_tz(to_timestamp(HIRE_DATE,'DD-MM-YY HH24:MI:SS'), 'America/Los_Angeles') at time zone 'UTC' from TABLE
OUTPUT: 19/04/2030 12:00:00 AM
If HIRE_DATE is a DATE data type then you don't need TO_TIMESTAMP.
TO_TIMESTAMP is used to convert a string (i.e. VARCHAR2) into a TIMESTAMP value but you have a DATE value.
Just do
select from_tz(CAST(HIRE_DATE AS TIMESTAMP), 'America/Los_Angeles') at time zone 'UTC'
from TABLE
Actually I don't understand why FROM_TZ does not accept DATE values whereas almost any other date/timestamp related function accept either DATE or TIMESTAMP value as input.
Note, the default output display format of this query is defined by current user session NLS_TIMESTAMP_TZ_FORMAT setting. If you are not satisfied with the output format, either change NLS_TIMESTAMP_TZ_FORMAT setting by executing ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = '...' or use TO_CHAR function to set output format explicitly.
Instead of
... AT TIME ZONE 'UTC'
you can also use
SYS_EXTRACT_UTC(...)
The upper returns a TIMESTAMP WITH TIME ZONE value, the second one returns a TIMESTAMP value.
Would this do any good?
SQL> select from_tz(cast (sysdate as timestamp), 'UTC') result from dual;
RESULT
---------------------------------------------------------------------------
27.09.20 10:59:28,000000 UTC
Or, in your case
select from_tz(cast (hire_date as timestamp), 'UTC' from dual
No need to apply any format mask to hire_date as it is a DATE datatype (at least, that's what you said).
You use the word "convert" which can mean one of two things:
change the data type, which is what FROM_TZ does
change the value from one time zone to another, which FROM_TZ does not do.
You didn't give your expected output, so we may misunderstand.
To change the data type:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select from_tz(cast(dte as timestamp), 'America/Los_Angeles') from data
FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES')
30-APR-19 12.00.00.000000 PM AMERICA/LOS_ANGELES
To get the simultaneous datetime value in UTC:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select cast(sys_extract_utc(from_tz(cast(dte as timestamp), 'America/Los_Angeles')) as date) from data
CAST(SYS_EXTRACT_UTC(FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES'))ASDATE)
2019-04-30 19:00:00

Date_Trunc and To_Date Questions SQL

Can we use date_trunc for a date (not date-time) that we are trying to "truncate" (not sure if the term can be applied here) to e.g. the start of the week? So if I have date_trunc(week, 28/10/2020) and I want to get the start of the week that 28th of October lies in (so 26th of October)? I tried this in my SQL command line but I get error messages.
If I am doing: SELECT to_date ('02 Oct 2001', 'DD Mon YYYY'); How can I ensure the resulting format is in a date format I specify (rather than the default date format)? For example if I want it in format DD-MM-YYYY?
select to_char(date '2017-06-02', 'MM') < in this example, why do we need "date" for this to work? The general format for to_char should be TO_CHAR (timestamp_expression, 'format'). I don't see in this general format that we need "day".
if I have a WHERE filter like to_char(order_date, '20-10-2020'), and there are indeed some rows with this order date, will these rows still show in my results (after running query) if these rows are in DATE format (so 20 Oct is in date format) as opposed to string (which is what I am filtering by as I am doing to_char). I know there would be no need to use to_char in this case but just asking..
yes, you can use date in text form but you have to cast it to a correct type
these queries will work
select date_trunc('week', '2020-10-28'::date);
select date_trunc('week', '10/28/2020'::date);
-- as well as
select date_trunc('week', '2020-10-28'::datetime);
and return timestamp 2020-10-26 00:00:00.000000
note, next query
select date_trunc('week', '28/10/2020'::date);
will fail with error date/time field value out of range: "28/10/2020";
You can use to_char, it returns text, if you need a date format you have to case it again
select to_char( to_date ('02 Oct 2001', 'DD Mon YYYY'), 'DD-MM-YYYY')::date;
select to_char('02 Oct 2001'::date, 'DD-MM-YYYY')::date;
'2017-06-02' is a text and it can't be automatically converted to timestamp. Actually I don't know a text format which can.
No, you need to explicitly cast into date type to use it as a filter
where order_date = date_stored_as_a_text::date
I am answering the questions in a different order as there are some wrong assumptions:
Question 3
There is a general difference between '2017-06-02' and date '2017-06-02' - the first one is just a varchar, a string, NOT handled as a date by Redshift, the 2nd one tells Redshift to handle the string as date and therefore works.
Question 2
A date data type column has no format - you may an sql client that can display date columns in different formats, however, this is not a functionality of redshift. SELECT to_date ('02 Oct 2001', 'DD Mon YYYY'); tells redshift to convert the string '02 Oct 2001' to date.
Question 1
DATE_TRUNC('datepart', timestamp) also supports week as datepart - see Date parts for date or timestamp function (Also shown in the example of AWS). You should also be able to provide a date instead of a timestamp.
Question 4
to_char(order_date, '20-10-2020')is not a filter and you are using it wrong.
AWS TO_CHAR
TO_CHAR converts a timestamp or numeric expression to a character-string data format.
I guess you are rather looking for:
where to_char(order_date, 'YYYY-MM-DD') = '20-10-2020'

How to convert 2020-08-20T12:02:02Z date into DD-MM-YYYY sql?

I want to convert "2020-08-20T12:02:02Z" date into DD-MM-YYYY in the oracle database. The date should look like 20-08-2020. Please advise.
You can try the below -
select to_char(
to_date('2020-08-20T12:02:02Z','YYYY-MM-DD"T"HH24:MI:SS"Z"'),
'DD-MM-YYYY')
from dual
TL;DR: Use TO_CHAR( column_name, 'DD-MM-YYYY' ) to explicitly format your DATE column.
A DATE column does not have a format; it is stored internally as 7-bytes (century, year-of-century, month, day, hour, minute and second respectively). It is not until a user interface tries to display the date that the displayed value is implicitly formatted based on the NLS_DATE_FORMAT session parameter (and this can be set by any user at any time within their own session so multiple users can have multiple date formats and these implicit formats can be changed mid-session so you should NEVER rely on implicit formatting to give consistent output).
So, if you have a DATE and its value is 2020-08-20T12:02:02Z then all you need to do is to format it when displaying it (using TO_CHAR) to not display the time component:
CREATE TABLE table_name (
column_name DATE
);
INSERT INTO table_name ( column_name )
VALUES ( DATE '2020-08-20' + INTERVAL '12:02:02' HOUR TO SECOND );
Set the implicit format for dates:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS"Z"';
Then:
SELECT column_name AS with_implicit_formatting,
TO_CHAR( column_name, 'DD-MM-YYYY' ) AS with_explicit_formatting
FROM table_name;
Outputs:
WITH_IMPLICIT_FORMATTING | WITH_EXPLICIT_FORMATTING
:----------------------- | :-----------------------
2020-08-20T12:02:02Z | 20-08-2020
db<>fiddle here
Note: the Z format model implies the Zulu (UTC+0) time zone. However, dates do not store time zones; so if you want to store this time-zone information then you should be using a TIMESTAMP WITH TIME ZONE data type rather than a DATE (and you may need to pay extra care when converting date-time values from a local time zone to UTC+0 that you apply the correct time zone offset to convert to UTC+0 and do not just take the date-time component and ignore the local time zone.

Filtering a dataset by date and time Oracle SQL through Power BI

I'm having trouble with filtering a date and time for anything two hours before and sooner. I tried this:
SELECT *
FROM
table
where
date >= sysdate - 1
AND
TO_DATE( Time, 'HH24:MI:SS' ) >= TO_DATE( sysdate, 'HH24:MI:SS' ) - 2
But I'm getting an inconsistent type error which is what I thought I was handling with the TO_DATE() function but I guess not.
sysdate is already a date (and time), so TO_DATE( sysdate, 'HH24:MI:SS' ) doesn't make any sense.
You didn't provide your data types for your date and time columns in table, so I'm going to assume they're both varchar2(10) with formats MM/DD/YYYY and HH24:MI:SS respectively.
I'm also going to go ahead and change your example table and column names, since they're invalid names to use in a real query.
-- example data
with my_table as (select '06/13/2019' as date_column, '09:40:34' as time_column from dual)
-- your query
SELECT *
FROM
my_table
where
to_date(date_column || ' ' || time_column, 'MM/DD/YYYY HH24:MI:SS') >= sysdate - 2/24
What I'm doing here is to combine your date and time strings into one date-time string, then converting it to an Oracle date type (actually date+time). Then we compare it to sysdate - 2/24, which says to take the current time and subtract 2/24ths of a day, which is 2 hours.
For this example, you might need to change the example data date_column and time_column values to something from the past 2 hours, depending on when you run this and what time zone you're in.

Issue with date in oracle

I am trying to pull date from one table which is in ISO format and then store it in US date format?
Trunc(cast(to_timestamp(ATTRIBUTE_39,'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"')as date))
Actual output:
4/11/2018 12:00:00 AM
expected output:
4/11/2018
I am trying to pull date from one table which is in ISO format and then store it in US date format?
Dates (and timestamps) do not have a format - they are represented in a table by 7 bytes for a date or 20 bytes for a timestamp.
You can get the value as a DATE data type using TO_TIMESTAMP_TZ and either the TZR or TZH:THM format models to match the time zone region/offset (they will both work with the Zulu time zone region)
SELECT CAST(
TO_TIMESTAMP_TZ(
ATTRIBUTE_39,
'yyyy-mm-dd"T"hh24:mi:ss.ff3TZH:TZM'
) AT TIME ZONE 'UTC' -- Convert to a common time zone
AS DATE
)
FROM your_table;
When you select from the table then whatever client program you are using (typically) will implicitly convert the 7-bytes it uses internally to something you, the user, can read - a string. SQL/Plus and SQL Developer use the NLS_DATE_FORMAT session parameter as the format model when they perform this implicit conversion.
So your query is effectively converted to:
SELECT TO_CHAR(
CAST(
TO_TIMESTAMP_TZ(
ATTRIBUTE_39,
'yyyy-mm-dd"T"hh24:mi:ss.ff3TZR'
) AT TIME ZONE 'UTC'
AS DATE
),
(
SELECT VALUE
FROM NLS_SESSION_PARAMETERS
WHERE PARAMETER = 'NLS_DATE_FORMAT'
)
)
FROM your_table;
If you want to format a date or a timestamp then you will have to explicitly convert it to a string using TO_CHAR():
SELECT TO_CHAR(
CAST(
TO_TIMESTAMP_TZ(
ATTRIBUTE_39,
'yyyy-mm-dd"T"hh24:mi:ss.ff3TZR'
) AT TIME ZONE 'UTC'
AS DATE
),
'MM/DD/YYYY'
)
FROM your_table;
Or by altering the NLS_DATE_FORMAT session parameter:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
(Be aware that this will only change the format in the current session and will not change it for any other sessions/users.)
Try this:
select to_char(Trunc(cast(to_timestamp('2016-06-29T13:13:00.123','yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"')as date)),'MM/DD/YYYY') from dual
the default date/time formatting depends on your NLS_DATE_FORMAT setting.