I have this value:
Thu Jan 01 01:00:00 UZT 1970
I need this value from the above value:
Thu Jan 1970
Need Substring from this value.
Use TO_DATE then TO_CHAR:
SELECT TO_CHAR(
TO_DATE(
'Thu Jan 01 01:00:00 UZT 1970',
'Dy Mon DD HH24:MI:SS "UZT" YYYY'
),
'Dy Mon YYYY'
) AS substring
FROM DUAL
| SUBSTRING |
| :----------- |
| Thu Jan 1970 |
db<>fiddle here
If you want it as DD-MM-YYYY format then change the format model used in TO_CHAR to 'DD-MM-YYYY' but if you are going to be storing it in the database it would be better to just store it as a date value rather than as a formatted string.
I have some columns "UZT" and some "UZST" then getting error on "UZST"
If those are the only time zones and you are not worried if there is an hours difference between the two zones then you can use:
SELECT TO_CHAR(
TO_DATE(
REPLACE( your_column, 'UZST', 'UZT' ),
'Dy Mon DD HH24:MI:SS "UZT" YYYY'
),
'Dy Mon YYYY'
) AS substring
FROM your_table
or if you need to account for the time zones (replace the time zone values as appropriate):
SELECT TO_CHAR(
TO_TIMESTAMP_TZ(
REPLACE(
REPLACE(
your_column,
'UZST',
'+05:00'
),
'UZT',
'+05:00'
),
'Dy Mon DD HH24:MI:SS TZH:TZM YYYY'
) AT TIME ZONE '+05:00',
'Dy Mon YYYY'
) AS substring
FROM your_table
Looks like a string. If that's so, here's one (actually, two) options:
SQL> with test (col) as
2 (select 'Thu Jan 01 01:00:00 UZT 1970' from dual)
3 select substr(col, 1, instr(col, ' ', 1, 2)) || substr(col, -4) result,
4 regexp_substr(col, '(\w+ ){2}') || regexp_substr(col, '\d+$') result2
5 from test;
RESULT RESULT2
------------ ------------
Thu Jan 1970 Thu Jan 1970
SQL>
[EDIT]
How to convert it to a different format? By applying TO_DATE (to convert "Thu Jan 1970", which is a string, to a valid DATE format), and then TO_CHAR with appropriate format mask to get what you want.
SQL> with test (col) as
2 (select 'Thu Jan 01 01:00:00 UZT 1970' from dual),
3 inter as
4 (select substr(col, 1, instr(col, ' ', 1, 2)) || substr(col, -4) result,
5 regexp_substr(col, '(\w+ ){2}') || regexp_substr(col, '\d+$') result2
6 from test
7 )
8 select to_char(to_date(result, 'dy mon yyyy', 'nls_date_language = english'), 'dd-mm-yyyy') new_result
9 from inter;
NEW_RESULT
----------
01-01-1970
SQL>
Related
How to display CST or CDT after the date & time, like shown below.
Sep 09 2022 10:30:32 PM CDT
Thanks.
Start with a TIMESTAMP WITH TIME ZONE data type of TIMESTAMP '2022-09-09 22:30:32 US/CENTRAL' and then format it using TO_CHAR and the format model 'Mon DD YYYY HH12:MI:SS AM TZD':
SELECT TO_CHAR(
TIMESTAMP '2022-09-09 22:30:32 US/CENTRAL',
'Mon DD YYYY HH12:MI:SS AM TZD',
'NLS_DATE_LANGUAGE=American'
) AS ts
FROM DUAL;
Which outputs:
TS
Sep 09 2022 10:30:32 PM CDT
If you have a DATE then cast it to a timestamp and use FROM_TZ to give it the US/CENTRAL time zone and then convert it to a string as above:
SELECT TO_CHAR(
FROM_TZ(
CAST(
DATE '2022-09-09' + INTERVAL '22:30:32' HOUR TO SECOND
AS TIMESTAMP
),
'US/CENTRAL'
),
'Mon DD YYYY HH12:MI:SS AM TZD',
'NLS_DATE_LANGUAGE=American'
) AS ts
FROM DUAL;
Which also outputs:
TS
Sep 09 2022 10:30:32 PM CDT
fiddle
Try something like this...
SELECT
To_Char(To_TimeStamp_TZ(To_Char(SYSDATE, 'Mon dd yyyy hh24:mi:ss'), 'Mon dd yyyy hh24:mi:ss ' || 'TZH:TZM'), 'Mon dd yyyy hh24:mi:ss ') ||
CASE To_Char(To_TimeStamp_TZ(To_Char(SYSDATE, 'Mon dd yyyy hh24:mi:ss'), 'Mon dd yyyy hh24:mi:ss ' || 'TZH:TZM'), 'TZH:TZM')
WHEN '-05:00' THEN 'CDT'
WHEN '-06:00' THEN 'CST'
-- ... ...
WHEN '+01:00' THEN 'CET'
WHEN '+02:00' THEN 'EET'
-- ... ... ...
ELSE
To_Char(To_TimeStamp_TZ(To_Char(SYSDATE, 'Mon dd yyyy hh24:mi:ss'), 'Mon dd yyyy hh24:mi:ss ' || 'TZH:TZM'), 'Mon dd yyyy hh24:mi:ss TZH:TZM')
END "DTM"
FROM DUAL
.... which in my case results as
-- DTM
-- ---------------------------
-- Oct 13 2022 19:19:03 EET
... OR if I exclude WHEN '+02:00' from case expresssion (forcing result to ELSE part)
-- DTM
-- ---------------------------
-- Oct 13 2022 19:22:07 +02:00
More about To_TimeStamp_TZ() function at: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions194.htm
Time zone definitions at: https://greenwichmeantime.com/time-zone/definition/
Regards...
I have a table I want to pull all date records before the most recent Friday. I know you can use sysdate (or getdate) to pull the current day, but all the solutions to similar questions I've looked at explicitly specify the numeric day of the week in the query. Todays Thursday so the below would work, but is there a dynamic alternative to this?
SELECT *
FROM table
WHERE datefield < sysdate - 6
You could use:
SELECT NEXT_DAY(TRUNC(SYSDATE) - 7, 'FRIDAY') AS last_friday
FROM DUAL;
However, if someone tries to query the data and is using a different language then you will get an error. I.e.:
ALTER SESSION SET NLS_DATE_LANGUAGE = 'FRENCH';
SELECT NEXT_DAY(TRUNC(SYSDATE) - 7, 'FRIDAY') AS last_friday
FROM DUAL;
Outputs:
ORA-01846: not a valid day of the week
A solution that works regardless of the language is to compare the day to the start of the ISO week (which is always a Monday):
SELECT TRUNC(SYSDATE, 'IW')
+ CASE WHEN SYSDATE - TRUNC(SYSDATE, 'IW') < 5
THEN -3
ELSE +4
END AS last_friday
FROM DUAL;
Outputs (with the NLS_DATE_FORMAT set to YYYY-MM-DD HH24:MI:SS (DY)):
LAST_FRIDAY
2022-01-14 00:00:00 (FRI)
db<>fiddle here
Your query would be:
SELECT *
FROM table
WHERE datefield < TRUNC(SYSDATE, 'IW')
+ CASE WHEN SYSDATE - TRUNC(SYSDATE, 'IW') < 5
THEN -3
ELSE +4
END
next_day function might help.
SQL> with test (datum) as
2 -- sample data; this January up to today
3 (select trunc(sysdate, 'mm') + level - 1
4 from dual
5 connect by level <= 20
6 )
7 select to_char(datum, 'dd.mm.yyyy, dy') datum
8 from test
9 where datum < next_day(sysdate - 7, 'FRIDAY')
10 order by datum;
DATUM
------------------------
01.01.2022, sat
02.01.2022, sun
03.01.2022, mon
04.01.2022, tue
05.01.2022, wed
06.01.2022, thu
07.01.2022, fri
08.01.2022, sat
09.01.2022, sun
10.01.2022, mon
11.01.2022, tue
12.01.2022, wed
13.01.2022, thu
14.01.2022, fri
14 rows selected.
SQL>
I have dates like this and I want to convert those short month names into numbers.
Sep 30 2021 19:00:04 +08
My desired output is either one of them.
2021/30/09 19:00:04 or 20213009190004
One option
SQL> with x ( string ) as ( select 'Sep 30 2021 19:00:04 +08' from dual )
2 select to_char(to_date(substr(string,0,length(string) - 3),'Mon DD YYYY HH24:MI:SS'),'YYYY/MM/DD HH24:MI:SS') from x ;
TO_CHAR(TO_DATE(SUB
-------------------
2021/09/30 19:00:04
SQL> with x ( string ) as ( select 'Sep 30 2021 19:00:04 +08' from dual )
2 select to_char(to_date(substr(string,0,length(string) - 3),'Mon DD YYYY HH24:MI:SS'),'YYYYMMDDHH24MISS') from x ;
TO_CHAR(TO_DAT
--------------
20210930190004
I have a column where I have several dates, as follows:
Sun Oct 22 05:35:03 2017
Mon Apr 16 14:33:43 2018
Fri Apr 13 10:41:43 2018
I've created a process to filter these dates and convert to YYYYMMDD, as below.
20171022
20180416
20180413
This result will be used to distribute the data in their respective partitions, which are daily.
I tried to do it this way but I did not succeed:
insert into table tab2
PARTITION (REFERENCE_DATE = from_unixtime (unix_timestamp ('Sun Oct 22 05:35:03 2017', 'E MMM dd HH: mm: ss yyyy'), 'yyyyMMdd'))
SELECT
from_unixtime (unix_timestamp ('Sun Oct 22 05:35:03 2017', 'E MMM dd HH: mm: ss yyyy'), 'yyyyMMdd') as reference_date
FROM tab1 LIMIT 100;
how to do this insert?
Use dynamic partition:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert into table tab2
PARTITION (REFERENCE_DATE)
SELECT
from_unixtime (unix_timestamp ('Sun Oct 22 05:35:03 2017', 'E MMM dd HH: mm: ss yyyy'), 'yyyyMMdd') as reference_date
FROM tab1 LIMIT 100;
Better use yyyy-MM-dd date format because this is native Hive date format:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert into table tab2
PARTITION (REFERENCE_DATE)
SELECT
from_unixtime (unix_timestamp('Sun Oct 22 05:35:03 2017', 'E MMM dd HH: mm: ss yyyy'), 'yyyy-MM-dd') as reference_date
FROM tab1 LIMIT 100;
This question already has answers here:
Calculate difference between 2 date / times in Oracle SQL
(21 answers)
Closed 9 years ago.
I have 2 dates with following format:
ST_DT = Sun Dec 29 11:55:29 EST 2013
ED_DT = Tue Dec 30 20:21:34 EST 2013
I want to find the difference between these 2 dates in HH:MM:SS format. Now my problem is that i don't know how to parse the above date format in Oracle.
Are the dates in varchar2 type? Then, you can first convert it into timestamp format. Since it has timezone also, use the to_timestamp_tz function.
SQL> select to_timestamp_tz('Sun Dec 29 11:55:29 EST 2013','Dy Mon dd hh24:mi:ss TZR yyyy') from dual;
TO_TIMESTAMP_TZ('SUNDEC2911:55:29EST2013','DYMONDDHH24:MI:SSTZRYYYY')
---------------------------------------------------------------------------
29-DEC-13 11.55.29.000000000 AM EST
Once the dates are in timestamp type, subtracting them will give you the difference in interval day to second type.
SQL> select to_timestamp_tz ('Mon Dec 30 20:21:34 EST 2013','Dy Mon dd hh24:mi:ss TZR yyyy')
2 - to_timestamp_tz ('Sun Dec 29 11:55:29 EST 2013','Dy Mon dd hh24:mi:ss TZR yyyy') from dual;
TO_TIMESTAMP_TZ('MONDEC3020:21:34EST2013','DYMONDDHH24:MI:SSTZRYYYY')-TO_TI
---------------------------------------------------------------------------
+000000001 08:26:05.000000000
Then use extract to get the individual components from the interval.
SQL> select extract(day from intrvl) as dd,
2 extract(hour from intrvl) as hh24,
3 extract(minute from intrvl) as mi,
4 extract(second from intrvl) as ss
5 from (
6 select to_timestamp_tz ('Mon Dec 30 20:21:34 EST 2013','Dy Mon dd hh24:mi:ss TZR yyyy')
7 - to_timestamp_tz ('Sun Dec 29 11:55:29 EST 2013','Dy Mon dd hh24:mi:ss TZR yyyy') as intrvl
8 from dual
9 );
DD HH24 MI SS
---------- ---------- ---------- ----------
1 8 26 5
I figured out one solution but it will work only for same time zone dates.
with tab as (
select to_date(replace(substr('Sun Dec 28 23:59:59 EST 2013', 4), 'EST '), 'Mon DD HH24:MI:SS RRRR') start_date,
to_date(replace(substr('Tue Dec 30 20:21:34 EST 2013', 4), 'EST '), 'Mon DD HH24:MI:SS RRRR') end_date
from dual),
tab_sec as
(select ((end_date - start_date) * 24 * 60 * 60) sec from tab)
select lpad(trunc(sec / (60*60)), 2, '0')||':'||
lpad(trunc((sec - (trunc(sec / (60*60)) * 60 * 60))/60), 2, '0')||':'||
lpad(mod(sec, 60), 2, '0') diff
from tab_sec;
You can use NUMTODSINTERVAL
For example
with x as (
select to_date('01/01/2014 10:00:00','dd/mm/yyyy hh24:mi:ss') d1 ,
to_date('01/01/2014 12:00:00','dd/mm/yyyy hh24:mi:ss') d2
from dual
union all
select to_date('02/01/2014 10:00:00','dd/mm/yyyy hh24:mi:ss') d1 ,
to_date('01/01/2014 12:00:00','dd/mm/yyyy hh24:mi:ss') d2
from dual
union all
select to_date('01/01/2014 10:30:00','dd/mm/yyyy hh24:mi:ss') d1 ,
to_date('01/01/2014 12:00:00','dd/mm/yyyy hh24:mi:ss') d2
from dual
union all
select to_date('01/01/2014 10:00:30','dd/mm/yyyy hh24:mi:ss') d1 ,
to_date('01/01/2014 12:00:00','dd/mm/yyyy hh24:mi:ss') d2
from dual
union all
select to_date('01/01/2014 10:00:30','dd/mm/yyyy hh24:mi:ss') d1 ,
to_date('02/01/2014 12:20:10','dd/mm/yyyy hh24:mi:ss') d2
from dual
)
select d1 , d2 , numtodsinterval(d2 - d1, 'day') as interval_diff
from x
D1 D2 INTERVAL_DIFF
------------------- ------------------- ---------------------------------
01/01/2014 10:00:00 01/01/2014 12:00:00 +000000000 02:00:00.000000000
02/01/2014 10:00:00 01/01/2014 12:00:00 -000000000 22:00:00.000000000
01/01/2014 10:30:00 01/01/2014 12:00:00 +000000000 01:30:00.000000000
01/01/2014 10:00:30 01/01/2014 12:00:00 +000000000 01:59:30.000000000
01/01/2014 10:00:30 02/01/2014 12:20:10 +000000001 02:19:39.999999999