Extract date (yyyy/mm/dd) from a timestamp in PostgreSQL - sql

I want to extract just the date part from a timestamp in PostgreSQL.
I need it to be a postgresql DATE type so I can insert it into another table that expects a DATE value.
For example, if I have 2011/05/26 09:00:00, I want 2011/05/26
I tried casting, but I only get 2011:
timestamp:date
cast(timestamp as date)
I tried to_char() with to_date():
SELECT to_date(to_char(timestamp, 'YYYY/MM/DD'), 'YYYY/MM/DD')
FROM val3 WHERE id=1;
I tried to make it a function:
CREATE OR REPLACE FUNCTION testing() RETURNS void AS '
DECLARE i_date DATE;
BEGIN
SELECT to_date(to_char(val1, "YYYY/MM/DD"),"YYYY/MM/DD")
INTO i_date FROM exampTable WHERE id=1;
INSERT INTO foo(testd) VALUES (i);
END
What is the best way to extract date (yyyy/mm/dd) from a timestamp in PostgreSQL?

You can cast your timestamp to a date by suffixing it with ::date. Here, in psql, is a timestamp:
# select '2010-01-01 12:00:00'::timestamp;
timestamp
---------------------
2010-01-01 12:00:00
Now we'll cast it to a date:
wconrad=# select '2010-01-01 12:00:00'::timestamp::date;
date
------------
2010-01-01
On the other hand you can use date_trunc function. The difference between them is that the latter returns the same data type like timestamptz keeping your time zone intact (if you need it).
=> select date_trunc('day', now());
date_trunc
------------------------
2015-12-15 00:00:00+02
(1 row)

Use the date function:
select date(timestamp_field) from table
From a character field representation to a date you can use:
select date(substring('2011/05/26 09:00:00' from 1 for 10));
Test code:
create table test_table (timestamp_field timestamp);
insert into test_table (timestamp_field) values(current_timestamp);
select timestamp_field, date(timestamp_field) from test_table;
Test result:

Have you tried to cast it to a date, with <mydatetime>::date ?

In postgres simply :
TO_CHAR(timestamp_column, 'DD/MM/YYYY') as submission_date

This works for me in python 2.7
select some_date::DATE from some_table;

Just do select date(timestamp_column) and you would get the only the date part.
Sometimes doing select timestamp_column::date may return date 00:00:00 where it doesn't remove the 00:00:00 part. But I have seen date(timestamp_column) to work perfectly in all the cases. Hope this helps.

CREATE TABLE sometable (t TIMESTAMP, d DATE);
INSERT INTO sometable SELECT '2011/05/26 09:00:00';
UPDATE sometable SET d = t; -- OK
-- UPDATE sometable SET d = t::date; OK
-- UPDATE sometable SET d = CAST (t AS date); OK
-- UPDATE sometable SET d = date(t); OK
SELECT * FROM sometable ;
t | d
---------------------+------------
2011-05-26 09:00:00 | 2011-05-26
(1 row)
Another test kit:
SELECT pg_catalog.date(t) FROM sometable;
date
------------
2011-05-26
(1 row)
SHOW datestyle ;
DateStyle
-----------
ISO, MDY
(1 row)

You can use date_trunc('day', field).
select date_trunc('day', data_gps) as date_description from some_table;

Related

how to fetch records between two timestamps in oracle?

I have a column of TIMESTAMP(6) datatype in oracle and have values like 2022-04-01 18:02:42 and i wanna fetch all the records that falls between two datetime. I tried like below but no luck,
select * from table
where column BETWEEN '2022-04-01 18:02:42' and '2022-11-03 19:28:57' -- no records
tried this too,
select *
from table
where column BETWEEN to_date('2022-04-01','yyyy-mm-dd')
and to_date('2022-11-03','yyyy-mm-dd') -- a non-numeric character was found where a numeric was expected
and,
select *
from table
where column BETWEEN to_timestamp('2022-04-01','yyyy-mm-dd')
and to_timestamp('2022-11-03','yyyy-mm-dd') -- a non-numeric character was found where a numeric was expected.
I want to fetch records falls in this dates!
Thanks.
You need to convert the literal into DATE using TO_DATE and required format mask to compare the timestamp column with the input timestamp values.
SQL> CREATE TABLE t(A TIMESTAMP);
Table created.
SQL>
SQL> INSERT INTO t(A) VALUES(to_date('2022-04-10T15:39:00', 'YYYY-MM-DD"T"HH24:MI:SS'));
1 row created.
SQL> INSERT INTO t(A) VALUES(to_date('2022-05-01T15:39:00', 'YYYY-MM-DD"T"HH24:MI:SS'));
1 row created.
SQL> INSERT INTO t(A) VALUES(to_date('2022-03-01T15:39:00', 'YYYY-MM-DD"T"HH24:MI:SS'));
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT * FROM t;
A
----------------------------
10-APR-22 03.39.00.000000 PM
01-MAY-22 03.39.00.000000 PM
01-MAR-22 03.39.00.000000 PM
SELECT *
FROM t
WHERE A BETWEEN
to_date('2015-04-06T15:39:00', 'YYYY-MM-DD"T"HH24:MI:SS')
AND
to_date('2022-05-06T15:39:00', 'YYYY-MM-DD"T"HH24:MI:SS');
A
--------------------------------------------------------------------------
10-APR-22 03.39.00.000000 PM
01-MAY-22 03.39.00.000000 PM
Use TIMESTAMP literals:
SELECT *
FROM table_name
WHERE column_name BETWEEN TIMESTAMP '2022-04-01 18:02:42'
AND TIMESTAMP '2022-11-03 19:28:57';
or DATE and INTERVAL DAY TO SECOND literals:
SELECT *
FROM table_name
WHERE column_name BETWEEN DATE '2022-04-01' + INTERVAL '18:02:42' HOUR TO SECOND
AND DATE '2022-11-03' + INTERVAL '19:28:57' HOUR TO SECOND;
or TO_TIMESTAMP:
SELECT *
FROM table_name
WHERE column_name BETWEEN TO_TIMESTAMP('2022-04-01 18:02:42', 'YYYY-MM-DD HH24:MI:SS')
AND TO_TIMESTAMP('2022-11-03 19:28:57', 'YYYY-MM-DD HH24:MI:SS');
or TO_DATE:
SELECT *
FROM table_name
WHERE column_name BETWEEN TO_DATE('2022-04-01 18:02:42', 'YYYY-MM-DD HH24:MI:SS')
AND TO_DATE('2022-11-03 19:28:57', 'YYYY-MM-DD HH24:MI:SS');
Firstly have to change NLS_DATE_FORMAT as follows:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD';
ALTER SESSION SET NLS_DATE_FORMAT = 'HH24:MI:SS';
Then running the query using TIMESTAMP literal as follows:
SELECT * FROM table_name WHERE column_name BETWEEN TIMESTAMP '2022-04-01 18:02:42' AND TIMESTAMP '2022-11-03 19:28:57';

how to insert 0001 year in oracle?

how to insert 0001 year in oracle ?
I've tried
UPDATE table1
SET
datblock = to_timestamp('01/01/0001 00:00:00,000000000','DD/MM/RR HH24:MI:SSXFF')
but it shows as 2001, anyone can help ?
Do not use the RR format which has a special logik to decide the century.
Use explicite YYYY format
select to_timestamp('01/01/0001 00:00:00,000000000','DD/MM/RR HH24:MI:SSXFF') yyyy from dual;
YYYY
-----------------------------
01.01.0001 00:00:00,000000000
Use a timestamp literal:
UPDATE table1
SET
datblock = TIMESTAMP '0001-01-01 00:00:00';
However, your query works as the string-to-date conversion rules mean that RR also matches RRRR.
CREATE TABLE table1 (datblock) AS
SELECT TIMESTAMP '2021-09-27 01:23:45' FROM DUAL;
ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SSXFF';
ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ',.';
UPDATE table1
SET datblock = to_timestamp(
'01/01/0001 00:00:00,000000000',
'DD/MM/RR HH24:MI:SSXFF'
);
SELECT * FROM table1;
Outputs:
DATBLOCK
0001-01-01 00:00:00,000000000
db<>fiddle here

removing milliseconds from a oracle tmstmp field

I have a TIMESTAMP(6) field in Oracle and I need to remove the millisecond component from the time.
For example I have
10/20/2014 10:34:06.356000 AM
and I would like to remove the milliseconds so that I have
10/20/2014 10:34:06 AM
Do you know the best way to do this?
Thank you!
How about this?
select cast(col as timestamp(0))
EDIT:
The easiest way to avoid rounding is to use trunc() or to subtract half a second:
select cast(col - 0.5/(24*60*60) as timestamp(0))
try this
SELECT TO_CHAR(SYSDATE, 'MM-DD-YYYY HH24:MI:SS') "NOW"
FROM DUAL;
if you need 12-hour date format
SELECT TO_CHAR(SYSDATE, 'MM-DD-YYYY HH:MI:SS AM') "NOW"
FROM DUAL;
SQL FIDDLE
You can either cast it to a timestamp with no fractional seconds (this will round to the nearest second):
CAST( your_timestamp AS TIMESTAMP(0) )
Or to a DATE data type (this will truncate to the nearest second):
CAST( your_timestamp AS DATE )
If you want it as a TIMESTAMP(0) data type then cast it back:
CAST( CAST( your_timestamp AS DATE ) AS TIMESTAMP(0) )
Or you can convert it to a formatted string and specify the format model you want to use (this will truncate to the nearest second):
TO_CHAR( your_timestamp, 'YYYY-MM-DD HH24:MI:SS' )
Like this:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE your_table ( your_timestamp ) AS
SELECT TIMESTAMP '2017-10-25 12:53:12.10076' FROM DUAL;
Query 1:
SELECT CAST( your_timestamp AS TIMESTAMP(0) ) AS "Timestamp",
CAST( your_timestamp AS DATE ) AS "Date",
TO_CHAR( your_timestamp, 'DD-MM-YYYY HH24:MI:SS' ) AS "String"
FROM your_table
Results:
| Timestamp | Date | String |
|-----------------------|----------------------|---------------------|
| 2017-10-25 12:53:12.0 | 2017-10-25T12:53:12Z | 25-10-2017 12:53:12 |
note: How the TIMESTAMP and DATE are formatted in the output will depend on your NLS_TIMESTAMP_FORMAT and NLS_DATE_FORMAT session parameters but you can directly control the formatting of TO_CHAR when you specify a format model.
This might help!
select substr(to_char('10/20/2014 10:34:06.356000 AM'),1,instr(to_char('10/20/2014 10:34:06.356000 AM'),'.')-1)||' '||
substr(to_char('10/20/2014 10:34:06.356000 AM'),-2,instr(to_char('10/20/2014 10:34:06.356000 AM'),'.')-1) "Date"
from dual;

How to convert date to a different format in SQL?

I do have this sample value of "12/01/2013" which is a string.
How can I convert it directly to an SQL statement? The format must be in INT, like this: 20131201
So from "12/01/2013" to 20131201.
See Data Type Formatting functions
select cast(to_char(to_timestamp('12/01/2013', 'MM/DD/YYYY'), 'YYYYMMDD') as int)
this works with SQL Server
SELECT CONVERT(INT, SUBSTRING('12/01/2013',7,4) +
SUBSTRING('12/01/2013',0,3) +
SUBSTRING('12/01/2013',4,2)) AS dateInt
Result
20131201
Tested in MySQL:
SELECT CAST(CONCAT(SUBSTR("12/01/2013",7,4), SUBSTR("12/01/2013",4,2),SUBSTR("12/01/2013",1,2)) AS UNSIGNED INTEGER);
In postgreSQL you have the to_date function which accepts a date string and a format string and returns a date.
So you can:
postgres=# select to_date('12/01/2015', 'mm/dd/yyyy');
to_date
------------
2015-12-01
(1 row)
postgres=# select to_date('12012015', 'mmddyyyy');
to_date
------------
2015-12-01
(1 row)
You can do it using CONVERT and REPLACE function like below.
DECLARE #dateValue date
SET #dateValue = CONVERT(DATETIME,'12/01/2013',102)
SELECT REPLACE ( CONVERT(nvarchar,#dateValue) , '-' , '' )
Rsult will be
20131201

Difference between two dates

I have a table that has the following data
fromDate | toDate
20JAN11 | 29DEC30
Both dates are for the 21st Century (i.e. 2011 and 2030) but only the last two characters are stored.
Why is the following statement (when run from within a PL/SQL module) against the above data always returns a positive value
dateDifference := (fromDate - toDate)
If i run the following statement from sqlplus i get the correct negative value which is correct.
select to_date('20JAN11','DDMONYY')-to_Date('29DEC30','DDMONYY') from dual;
I remember reading somewhere that Oracle would sometimes use the wrong century but i dont quite remember the exact scenario where that would happen.
Assuming those columns are of DATE datatype, which seems to be the case: Oracle always stores DATE values in an internal format which includes the full year. The fact that you are seeing only a 2-digit year has to do with the date format used to convert the date to a string for display. So most likely the stored century values are not what you think they are.
Try selecting the dates with an explicit format to see what you really have stored:
SELECT TO_CHAR( fromDate, 'DD-MON-YYYY' ), TO_CHAR( toDate, 'DD-MON-YYYY' )
Seems to work for me either way on my 10g database:
SQL> set serveroutput on
SQL>
SQL> DECLARE
2 d1 DATE := to_date('20JAN11','DDMONRR');
3 d2 DATE := to_date('29DEC30','DDMONRR');
4 diff INTEGER;
5 BEGIN
6 diff := d1 - d2;
7 dbms_output.put_line(diff);
8 END;
9 /
-7283
PL/SQL procedure successfully completed
SQL>
EDIT: works for YY instead of RR year format as well.
EDIT2: Something like this, you mean?
SQL> create table t (d1 date, d2 date);
Table created
SQL> insert into t values (to_date('20JAN11','DDMONYY'), to_date('29DEC30','DDMONYY'));
1 row inserted
SQL> commit;
Commit complete
SQL>
SQL> DECLARE
2 R t%ROWTYPE;
3 diff INTEGER;
4 BEGIN
5 SELECT d1, d2
6 INTO R
7 FROM t;
8 diff := R.d1 - R.d2;
9 dbms_output.put_line(diff);
10 END;
11 /
-7283
PL/SQL procedure successfully completed
SQL>
As #Alex states, you may want to verify your data.
works without formatting as well
CREATE TABLE DATETEST(FROMDATE DATE, TODATE DATE);
insert into DATETEST (fromdate,todate) values (to_date('20Jan11','ddMonrr'),to_date('29DEC30','ddMonrr'));
SELECT TO_CHAR(FROMDATE,'ddMonrrrr hh24:mi:ss') FROMDATE,
TO_CHAR(TODATE,'ddMonrrrr hh24:mi:ss') TODATE
from datetest ;
/*
FROMDATE TODATE
------------------ ------------------
20Jan2011 00:00:00 29Dec2030 00:00:00
*/
set serveroutput on
DECLARE
l_FROMDATE DATETEST.FROMDATE%type ;
L_TODATE DATETEST.TODATE%TYPE;
dateDifference number;
BEGIN
--notice -- no formatting just putting them into a variable for test
SELECT FROMDATE, TODATE
INTO L_FROMDATE, L_TODATE
from datetest;
DATEDIFFERENCE := L_FROMDATE - L_TODATE ;
DBMS_OUTPUT.PUT_LINE('DATEDIFFERENCE = ' || DATEDIFFERENCE );
end ;
--DATEDIFFERENCE = -7283
SELECT FROMDATE-TODATE
from datetest ;
/* --still not formatting
FROMDATE-TODATE
----------------------
-7283
*/
SELECT (FROMDATE - TODATE) DATEDIFF,
TO_CHAR(FROMDATE,'ddMonrrrr') FROMDATE,
to_char(todate,'ddMonrrrr') todate
from (
SELECT TO_DATE('20JAN11','DDMONYY') FROMDATE,
TO_DATE('29DEC30','DDMONYY') TODATE
FROM DUAL)
;
/*
DATEDIFF FROMDATE TODATE
---------------------- --------- ---------
-7283 20Jan2011 29Dec2030
*/
try running the first query on your table:
SELECT TO_CHAR(FROMDATE,'ddMonrrrr hh24:mi:ss') FROMDATE,
TO_CHAR(TODATE,'ddMonrrrr hh24:mi:ss') TODATE
from datetest ;
see if the years are what you actually expect.
(Edit: changed to use two digit years)