How to get the first day of the week, depending on NLS - oracle

I want to get the date of the first day of the week but I want it to be dependant to NLS parameters. Say , when I run it on America it should give me Sundays date, but in Turkey it should give me Monday..
select trunc(to_date(sysdate,'dd-mm-yy'),'iw')from dual;
How can I make it dependant?

According to the documentation, trunc(sysdate, 'IW') gives you:
Same day of the week as the first day of the calendar week as defined by the ISO 8601 standard, which is Monday
As you've seen, that is clearly not NLS-dependent.
You might think using W would give you the non-ISO, NLS-dependent, version, but it does something different - the same day of the week as the first day of the month. So run now, that will give you Monday, regardless of your settings, since July 1st was a Monday.
So you need either D, DY or DAY - they all behave the same:
alter session set nls_territory = 'AMERICA';
select trunc(sysdate, 'D') from dual;
TRUNC(SYS
---------
14-JUL-13
alter session set nls_territory = 'TURKEY';
select trunc(sysdate, 'D') from dual;
TRUNC(SYSD
----------
15/07/2013
Incidentally, your original query is doing to_date(sysdate,'dd-mm-yy'). sysdate is already a date. You're forcing an implcit conversion from that date to a string, which will use your NLS_DATE_FORMAT, and then an explicit conversion back to a date using dd-mm-yy. Not only is that pointless, it would break if your NLS_DATE_FORMAT didn't match (roughly, there is quite a bit of leeway) the dd-mm-yy you use explicitly:
alter session set nls_date_format = 'dd/mm/yyyy';
select to_date(sysdate,'dd-mm-yy') from dual;
TO_DATE(SY
----------
18/07/2013
alter session set nls_date_format = 'dd-mon-rr';
select to_date(sysdate,'dd-mm-yy') from dual;
TO_DATE(S
---------
18-jul-13
alter session set nls_date_format = 'mm/dd/yyyy';
select to_date(sysdate,'dd-mm-yy') from dual;
select to_date(sysdate,'dd-mm-yy') from dual
*
ERROR at line 1:
ORA-01843: not a valid month
alter session set nls_date_format = 'yyyy-mm-dd';
select to_date(sysdate,'dd-mm-yy') from dual;
select to_date(sysdate,'dd-mm-yy') from dual
*
ERROR at line 1:
ORA-01861: literal does not match format string
... etc. And your NLS_DATE_FORMAT is inherited from NLS_TERRITORY by default, so this is likely to be an issue if you're expecting to deal with multiple regions anyway.

When u use iso week, it is same for all territories. It returns always mondays.
Instead of use this;
select sysdate your_date,
trunc(sysdate,'IW') iso_start_of_week,
to_char(sysdate,'D') your_territory_day,
trunc(sysdate)- to_char(sysdate,'D') + 1 this_is_what_u_want
from dual

Related

Charts in Oracle Apex

Hi everyone I wanna ask u about how I can bring data last 24 hours into bar charts, is there any methods to make it please
I have this table without data
datetime
clientchannel
servicename
service_count
13_02_2022 9:35
*****
notification
2
It is a WHERE clause you need, I presume. Something like this:
select ...
from your_table
where datetime >= sysdate - 1;
Why? Because - when you subtract a number from DATE datatype value in Oracle - it subtracts that many days.
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';
Session altered.
SQL> select sysdate right_now,
2 sysdate - 1 yesterday
3 from dual;
RIGHT_NOW YESTERDAY
------------------- -------------------
13.02.2022 11:01:34 12.02.2022 11:01:34
SQL>
If you store date values as strings (which means that DATETIME column is declared as e.g. VARCHAR2(20), and that's really bad idea), then you first have to convert it to a valid date datatype value - use TO_DATE function with appropriate format mask:
where to_date(datetime, 'dd_mm_yyyy hh24:mi') >= sysdate - 1
[EDIT] If you want to go 60 minutes back, then subtract that many minutes:
SQL> select sysdate right_now,
2 sysdate - interval '60' minute an_hour_ago
3 from dual;
RIGHT_NOW AN_HOUR_AGO
------------------- -------------------
14.02.2022 07:09:30 14.02.2022 06:09:30
SQL>

Error: ORA-01848: day of year must be between 1 and 365 (366 for leap year) while extracting month and year from DateColumn(varchar(10))

SELECT TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'YYYY-MM') as Date_y FROM Table_d
Even want to get quarter from the same date which is again giving me the error ORA-01848 like
SELECT (CASE WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('01','02','03') THEN 'Q1'
WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('04','05','06') THEN 'Q2'
WHEN (TO_CHAR(TO_DATE(Column_d, 'dd/mm/yyyy'), 'mm')) IN ('07','08','09') THEN 'Q3'
ELSE 'Q4' END as QTR
FROM Table_d
The way I see it, nothing of what you posted returns ORA-01848. It is - usually, if not always - related to the DDD date format mask which represents day number within the year.
For example, this is correct, as day number 001 equals the 1st of January:
SQL> select to_date('001-2020', 'ddd-yyyy') from dual;
TO_DATE('0
----------
01.01.2020
This returns ORA-01848 as there's no day 405 in this (nor any) year:
SQL> select to_date('405-2020', 'ddd-yyyy') from dual;
select to_date('405-2020', 'ddd-yyyy') from dual
*
ERROR at line 1:
ORA-01848: day of year must be between 1 and 365 (366 for leap year)
So: if you're doing anything like this, make sure that stored values are correct; I presume that not all of them are.
Besides, that's what happens when people store dates as strings into VARCHAR2 (instead of DATE datatype) columns. I'm not saying that you're the cause, but you certainly are a victim here.
[EDIT]
Julian date, eh? In a comment, you said that you used such a query:
Select TO_CHAR(TO_DATE(Julian_dateColumn+1900000, 'YYDDD'), 'YYDDD'), 'DD/MM/YYYY') as column_d from sometable
I doubt it as it is invalid (I suppose you have superfluous , 'YYDDD')).
Anyway, I have no idea why you tried to "convert" Julian date in such a manner. There's a simple and correct way to do so. Here's how:
This is today's date (21.05.2020) presented as Julian date:
SQL> select to_char(sysdate, 'j') julian from dual;
JULIAN
-------
2458991
That's kind of values you have stored in the table. In order to convert it to format you wanted (yyddd), you'd
SQL> select to_char(to_date(2458991, 'j'), 'yyddd') as column_d from dual;
COLUM
-----
20142
I suggest you use this instead of code you currently have, i.e.
SQL> create or replace view table_d as
2 select to_char(to_date(julian_datecolumn, 'j'), 'yyddd') as column_d
3 from sometable;
View created.
SQL> select * From table_d;
COLUM
-----
20142
SQL>

How to convert DATETIME in specific format to DATE in PL/SQL

I apologize for asking a simple question, but I could not find the answer on the forum.
I need to convert from this datetime '2009-06-18T00:00:00+06:00' to format 'YYYY-MM-DD' in PL/SQL.
If this "datetime" is really a timestamp (as it looks like), not a string, then you can choose how to display it (using TO_CHAR) or convert to DATE (using TO_DATE), or simply TRUNCATE it. Note that the last two results (i.e. the way they are displayed) depend on current NLS settings (set by my ALTER SESSION).
Here's an example:
SQL> alter session set nls_date_format = 'dd.mm.yyyy';
Session altered.
SQL> with test
2 as (select to_timestamp_tz ('2009-06-18T00:00:00+06:00',
3 'yyyy-mm-dd"t"hh24:mi:ss tzh:tzm')
4 col
5 from dual)
6 select to_char (col, 'yyyy-mm-dd') res1,
7 to_date (to_char (col, 'yyyy-mm-dd'), 'yyyy-mm-dd') res2,
8 trunc (col) res3
9 from test;
RES1 RES2 RES3
---------- ---------- ----------
2009-06-18 18.06.2009 18.06.2009
SQL>
Use TO_DATE on the first 10 characters in your timestamp string:
SELECT TO_DATE(SUBSTR('2009-06-18T00:00:00+06:00', 1, 10), 'YYYY-MM-DD') FROM dual
Demo
Documentation is the best part.
http://www.sqlines.com/oracle-to-sql-server/to_date
you can use the TO_DATE(string, format) function for that so it will be like
SELECT TO_DATE('2012-06-05', 'YYYY-MM-DD') FROM xyz;
DEPENDS on the data type.
If the column is DATE data type, then, as suggested already, TRUNC would do the job to display. But, if your locale-specific NLS date settings are different, then you will still see the time portion as midnight.
Else, you need to use TO_DATE with proper FORMAT and apply TRUNC to it.
update
If you only want to display, use TO_CHAR, else, if you have a filter in your WHERE clause, then remember TO_CHAR doesn't return DATE, it converts it into literal.

Use time in between in oracle for multiple date

Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
Note :
1. I need perticular time period only for 10 days
Error :
1. data is there but returning Zero kindly help to solve this
You need to use the full date and time TO_DATE otherwise there is conflicting WHERE clauses'DD/MM/RRRR hh24:mi:ss'.
SELECT *
FROM mytable
WHERE paid_time BETWEEN TO_DATE('01/08/2016 00:00:00', 'DD/MM/RRRR hh24:mi:ss') AND TO_DATE('10/08/2016 00:59:59', 'DD/MM/RRRR hh24:mi:ss');
If paid_time is a string then your query will only work at all for certain NLS_DATE_FORMAT settings, due to the implicit conversion you are forcing:
alter session set nls_date_format = 'RRRR-MM-DD';
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between to_date('00:00:00','HH24:MI:SS' ) and to_date('00:59:59','HH24:MI:SS')
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
no rows selected
alter session set nls_date_format = 'YYYY-MM-DD';
-- same query
ORA-01841: (full) year must be between -4713 and +9999, and not be 0
alter session set nls_date_format = 'DD/MM/RRRR';
-- same query
ORA-01847: day of month must be between 1 and last day of month
... etc.
When you do to_date('00:00:59','HH24:MI:SS') the generated date defaults to the first of the current month, so when run today it will get a September date:
select to_char(to_date('00:00:59','HH24:MI:SS'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2016-09-01 00:00:59
You are then trying to compare your paid_time string with that date, which means the string is implicitly converted to a date using your NLS settings, e.g.:
alter session set nls_date_format = 'RRRR-MM-DD';
select to_char(to_date('00:01:02'), 'YYYY-MM-DD HH24:MI:SS') from dual;
TO_CHAR(TO_DATE('00
-------------------
2000-01-02 00:00:00
So your filter is really looking for rows where the time string, incorrectly converted to a date (exactly which date depends on your actual NLS setting, and many values will error whatever the setting), is in the first minute of the first day of the current month. Which is very unlikely to ever match anything.
If it is a string and is always formatted consistently then you can just compare as a string:
with mytable (paid_date, paid_time) as (
select date '2016-08-02', '00:01:02' from dual
)
Select *
from mytable
where paid_time Between '00:00:00' and '00:59:59'
and paid_date Between to_date('1/8/2016','DD/MM/RRRR') and
to_date('10/8/2016','DD/MM/RRRR');
PAID_DATE PAID_TIM
---------- --------
2016-08-02 00:01:02
As mentioned in comments Oracle's data datatype includes the time, so storing the date (at midnight, presumably) and the time in separate columns just adds complexity and inefficiency.

Oracle date format problem

I have the following strange problem in Oracle
(Please keep in mind that I have little experience in SQL and even less in Oracle).
If I do this:
SELECT TO_CHAR(sysdate, 'YYYY-MM-DD HH24:MI') FROM dual
I get this:
2010-12-02 18:39
All fine there.
However, if I do this:
UPDATE favorite_item
SET favorite_item.last_used_date = TO_DATE(sysdate, 'YYYY-MM-DD HH24:MI')
WHERE favorite_item.favorite_item_id = 1
I get this in my database:
10-DEC-02
Which is the 10th of December '02 which is not correct
If I do this to confirm:
SELECT TO_CHAR(favorite_item.last_used_date, 'YYYY-MM-DD HH24:MI') AS last_used_date
FROM favorite_item
WHERE favorite_item.favorite_item_id = 1
I get this:
0002-12-10 00:00
Which is completely wrong.
What am I doing wrong? I feel that the date setting is not working correctly.
Thanks in advance for your help.
Don't use TO_DATE() on sysdate; sysdate is already a date.
UPDATE favorite_item
SET favorite_item.last_used_date = sysdate
WHERE favorite_item.favorite_item_id = 1`
The problem is using the to_date() function on anything other than a string.
As to why you are getting the wrong results, there is an internal conversion that happens when you use to_date on a date. Since to_date actually takes input as a string, your date is initially converted into a string (according to your NLS_DATE_FORMAT setting) and then converted back to a date. Hence the mismatch.
SQL> select sysdate from dual;
SYSDATE
---------
02-DEC-10
SQL> select to_date(sysdate,'YYYY-MM-DD') from dual;
TO_DATE(S
---------
10-DEC-02
--- This is because, the above string is actually executed as
SQL> select to_date(
to_char('02-DEC-10','YYYY-MM-DD') from dual;
TO_DATE('
---------
10-DEC-02
SQL> select to_date(
2 /* implicit conversion... dd-mon-yy' is my session's NLS_DATE_FORMAT */
3 to_char(sysdate,'dd-mon-yy'),
4 'YYYY-MM-DD')
5 from dual;
TO_DATE(/
---------
10-DEC-02
sysdate returns a date, so converting it to a date using to_date(sysdate, ...) is redundant/not necessary. You're getting that odd result because the date is being cast to a string by the to_date function using the Oracle default of "DD-MON-YY" and then back into a date using your supplied format, "YYYY-MM-DD". Since the formats don't match, Oracle is interpreting the year as the day and the day as the year. This works correctly (but, again, is redundant):
select to_date(sysdate, 'DD-MON-YY') from dual;

Resources