I am trying to convert a date column (ie. 2012-10-02) to the first day of the year with time (ie. 2012-01-01T00:00:00) in sql.
Is there a way to do so in the SELECT query?
for BigQuery use below
select timestamp_trunc('2012-10-02', year)
with output
2012-01-01 00:00:00 UTC
Note - if you column is of date type - the output will be
2012-01-01T00:00:00
and finally, you can use datetime_trunc instead of timestamp_trunc and you will get expected result - 2012-01-01T00:00:00
Look at the YEAR() function.
It would allow you to extract just the year, and then just as the date and time you need.
I want to calculate the difference between two dates, and get the day difference between these dates in Oracle.
Here is my code:
Select To_Date(TO_CHAR(sysdate, 'YYYY/MM/DD','nls_calendar=persian'))- TO_Date(TO_CHAR(SHF_Date))
from DtTable
But I get this error:
ORA-01861: literal does not match format string for case statement
sysdate is already a date, and shf_date also seems to be one. You don't need any conversion here, and can subtract them directly:
SELECT sysdate - SHF_Date FROM DtTable
If you want to use your statement
Select To_Date( TO_CHAR(sysdate, 'YYYY/MM/DD','nls_calendar=persian'), 'YYYY/MM/DD')- TO_Date(TO_CHAR(SHF_Date, 'YYYY/MM/DD'), 'YYYY/MM/DD') from DtTable;
But it does not make any sense.
Use it in this way
Select sysdate - hire_date from employees;
Storage format and display format are two different things. We let Oracle store data using its own internal format, which for DATE columns is a 7-byte binary value that is not human-readable.
How you choose to present the values in a report or application is another thing - for example, you could display the same number as 1000, 1,000 or 1e3, or display the same date as 2021-04-18 or Sunday 18th April. This is not related to how you store it. You cannot store any preferred display format. You have to handle the display format when you query it or in your application.
Also, in Oracle date arithmetic, subtracting one date from another gives a number of days, so trying to query to_date(date2 - date1) will never work, because how can it convert a number of days like 270 into a date?
create table dttable (shf_date date);
insert into dttable (shf_date)
values (to_date('1399/05/01','YYYY-MM-DD', 'nls_calendar=Persian'));
(Notice the definition of shf_date as an Oracle date. Is that how it is in your table?)
select to_char(shf_date, 'YYYY-MM-DD', 'nls_calendar=Gregorian') as shf_date_gregorian
, to_char(shf_date, 'YYYY-MM-DD', 'nls_calendar=Persian') as shf_date_shamsi
, trunc(sysdate - shf_date) as days_since_shf_date
from dttable;
SHF_DATE_GREGORIAN SHF_DATE_SHAMSI DAYS_SINCE_SHF_DATE
-------------------- --------------- -------------------
2020-07-22 1399-05-01 270
Although you've said several times that shf_date is a date, you've also said things like:
sysdate is : DD/MM/YYYY but shf_date is : YYYY/MM/DD
I run this code: select trunc(sysdate - shf_date) from dttable; but I get 'Invalid number' error.
Which means it is not a date, but is stored as a string. So, you need to convert that string to a date, in Gregorian calendar, so that actual date can be compared with sysdate.
Modifying and expanding William's example:
select sysdate as sysdate_date
, to_char(sysdate, 'YYYY-MM-DD', 'nls_calendar=Gregorian') as sysdate_gregorian
, to_char(sysdate, 'YYYY-MM-DD', 'nls_calendar=Persian') as sysdate_shamsi
, shf_date as shf_date_string
, to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian') as shf_date_date
, to_char(to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian'), 'YYYY-MM-DD', 'nls_calendar=Gregorian') as shf_date_gregorian
, to_char(to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian'), 'YYYY-MM-DD', 'nls_calendar=Persian') as shf_date_shamsi
, trunc(sysdate - to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian')) as days_since_shf_date
from dttable;
SYSDATE_DATE | SYSDATE_GREGORIAN | SYSDATE_SHAMSI | SHF_DATE_STRING | SHF_DATE_DATE | SHF_DATE_GREGORIAN | SHF_DATE_SHAMSI | DAYS_SINCE_SHF_DATE
:----------- | :---------------- | :------------- | :-------------- | :------------ | :----------------- | :-------------- | ------------------:
18-APR-21 | 2021-04-18 | 1400-01-29 | 1399/05/01 | 22-JUL-20 | 2020-07-22 | 1399-05-01 | 270
db<>fiddle
If you want to use this in a filter then you can do:
where trunc(sysdate - to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian')) = 270
or whatever comparison you need to perform.
The query in snowflake,
select date_column, try_to_date(date_column)
from tablename;
tends to mess up the intended dates as shown below:
01-NOV-18 ____________ 0018-11-01 (desired output 2018-11-01)
09-JAN-19 ____________ 0019-01-09
2018-11-03 20:44:54 __ 2018-11-03
2018-09-03 00:00:00 __ 2018-09-03
2018-08-22 19:38:41 __ 2018-08-22
This is similar to Snowsql two digit century start date cast issue, but with multiple date formats in the input column.
You could use a coalesce with the try_to_date. The key is to specifically put a date format in the try_to_date function so that it returns null if it can't convert a date that doesn't match the format. When the date doesn't match the format it'll fall back to the next method you specify and you can continue until you covered all your different date formats. Try something like:
select
date_column,
coalesce(try_to_date(date_column, 'YYYY-MM-DD HH:MI:SS'), try_to_date(date_column, 'DD-MON-YY'))
from tablename;
This returns:
+-------------------+----------------------------------------------------------------------------------------------+
|INPUT_DATE |COALESCE(TRY_TO_DATE(INPUT_DATE, 'YYYY-MM-DD HH:MI:SS'), TRY_TO_DATE(INPUT_DATE, 'DD-MON-YY'))|
+-------------------+----------------------------------------------------------------------------------------------+
|01-NOV-18 |2018-11-01 |
|09-JAN-19 |2019-01-09 |
|2018-11-03 20:44:54|2018-11-03 |
|2018-09-03 00:00:00|2018-09-03 |
|2018-08-22 19:38:41|2018-08-22 |
+-------------------+----------------------------------------------------------------------------------------------+
Whenever I create data after 5 PM PST (Pacific Standard Time), the manufactured_date column gets changed to next date.
For example, I entered new data today which is 2020-11-05 at 5:15 pm PST, the value that gets stored in manufactured_date column is 2020-10-06
Query select * from cars gives me below result
id | car_name | manufactured_date
---------------------------------
1 | Audi | 11-06-2020
2 | BMW | 11-06-2020
Here are the properties of cars table
column name | data type
-----------------------------
id | serial
car_name | varchar
manufactured_date | date
The insert query is
insert
into
cars (car_name, manufactured_date)
values ('Audi', '11-05-2020');
How can I eliminate this problem?
Use a case expression:
select (case when (now() now() at time zone 'PST')::time >= '17:00:00'::time
then manufactured_date + interval '1 day'
else manufactured_date
end)
The problem is most likely that the server is running in UTC and that is column is based on UTC instead of PST timezone.
to validate this you can just execute this and it should return the current timestamp according to server timezone:
select now()
This is really interesting! I couldn't reproduce your problem on my VM, even after playing with the OS time-zone settings and with the PGTZ environment variable.
Can you please try not counting on implicit data type conversions? Adding the DATE directive before what is currently a string literal might help:
INSERT INTO cars (car_name, manufactured_date)
VALUES ('Audi', DATE '2020-11-05');
I want to do something like CURRENT_DATE-number_of_days, which should return a date in format yyyy-MM-dd. Is this possible with Oracle database queries?
You can use SYSDATE (oracle specific) or CURRENT_DATE (ANSI) to get the current date/time.
In SQL Developer you can set the date format by going to "Tools" > "Preferences" and selecting the "Database" > "NLS" on the left hand side and then editing the Date Format.
If you want to use a different date format most of the time but in this singular instance want the date in ISO 8601 format (YYYY-MM-DD) then you can use TO_CHAR( date, 'YYYY-MM-DD') (but it will then return as a string rather than a date).
To add (subtract) days from a date then you can do one of several options (note: SQLFIDDLE has different NLS date formatting perameters on its output that you've specified, but it should give you the idea):
SQL Fiddle
Query 1:
SELECT CURRENT_DATE - INTERVAL '1' DAY,
CURRENT_DATE - 1
FROM DUAL
Results:
| CURRENT_DATE-INTERVAL'1'DAY | CURRENT_DATE-1 |
|-----------------------------|----------------------------|
| November, 12 2015 12:28:40 | November, 12 2015 12:28:40 |