Date Manipulation in Oracle SQL

AID: 5969
  • Status: Published

1707 points

  • Byianmills2002
  • TypeTips/Tricks
  • Posted on2011-06-03 at 00:31:19

Introduction


In any development project using SQL or PL/SQL, there is inevitably a DATE variable or column and you will have to do some type of manipulation to that date at some point. Some of the requirements are fairly straight forward, but others may require a little bit more thought to get the formula right.

Over my years in IT I have done my fair share of date manipulation. This includes SQL queries for reporting, Oracle jobs and many procedures and functions. In my most recent project at work, I have been working on a report scheduling where the schedules are recurring. As such, I have had to work out some simple and some more complex date manipulation formulas.

I thought I should share these because I know just how useful these tips can be when working out solutions.

In all my examples, my date input will be SYSDATE. With any formula given, just replace SYSDATE with any date that you need. I am using the TRUNC() function to remove the time portion from the date. Remove it if you wish to keep the time portion on the date.
To get an instant result when testing the formulas in the examples, I have used SELECT ... FROM DUAL. It may be better in your environment, especially for more complex formulas, to put the logic into functions or into a package if you end up with quite a few functions.


Some Simple Solutions


Tomorrow
SELECT TRUNC(SYSDATE + 1) FROM DUAL
                                    
1:

Select allOpen in new window


In 7 days
SELECT TRUNC(SYSDATE + 7) FROM DUAL
                                    
1:

Select allOpen in new window


First day of next month
SELECT TRUNC(LAST_DAY(SYSDATE) + 1) FROM DUAL
                                    
1:

Select allOpen in new window


Last day of next month
SELECT TRUNC(LAST_DAY(ADD_MONTHS(SYSDATE, 1))) FROM DUAL
                                    
1:

Select allOpen in new window


Next Tuesday
SELECT NEXT_DAY(TRUNC(SYSDATE), 'TUESDAY') FROM DUAL
                                    
1:

Select allOpen in new window


Replace TUESDAY with any required day of the week.

15th day of next month
SELECT TRUNC(LAST_DAY(SYSDATE) + 15) FROM DUAL
                                    
1:

Select allOpen in new window


Next Weekday at 2:30 PM
SELECT CASE WHEN TRIM(TO_CHAR(TRUNC(SYSDATE), 'DAY')) = 'SATURDAY' THEN TRUNC(TRUNC(SYSDATE) + 2) 
       ELSE TRUNC(SYSDATE) + 1
       END + 14.5/24
FROM DUAL
                                    
1:
2:
3:
4:

Select allOpen in new window


Next Weekday with Date and Time Substitution Variables
:pi_date : has to be in the format 'DD-MON-YYYY'
:pi_time : any number between 0 and 24
SELECT CASE WHEN TRIM(TO_CHAR(to_date(:pi_date, 'DD-MON-YYYY'), 'DAY')) = 'SATURDAY' THEN TRUNC(to_date(:pi_date, 'DD-MON-YYYY') + 2) 
       ELSE TRUNC(to_date(:pi_date, 'DD-MON-YYYY') + 1) 
       END + (:pi_time/24)
FROM DUAL
                                    
1:
2:
3:
4:

Select allOpen in new window


Next Non Weekday
SELECT CASE WHEN TRIM(TO_CHAR(TRUNC(SYSDATE), 'DAY')) = 'SATURDAY' THEN TRUNC(SYSDATE) + 1 
       ELSE NEXT_DAY(TRUNC(SYSDATE), 'SATURDAY')
       END
FROM DUAL
                                    
1:
2:
3:
4:

Select allOpen in new window




A More Complex Solution



Nth Day of the Week in a Month
How to dynamically calculate the Nth Day of the week within a month

Do you need to dynamically calculate the 3rd Tuesday of next month or something similar? Oracle has a simple way of doing this and can be expressed with the following formula.

NEXT_DAY(LAST_DAY(date), 'DAY') + (7 * (instance - 1)) + time

date - is the start date the calculation needs to start at
instance - which occurance of the day in the month
DAY - day of the week
time - time of day to add to the date (optional)

The LAST_DAY Oracle function returns the last day of the month after the date given.
The NEXT_DAY Oracle function will give you the 1st occurance of the DAY in the next month.
From there, you need to add 7 days for each recurring instance of the DAY in the next month.


Example 1 - 3rd Tuesday of the month at 10 am

date - TRUNC(SYSDATE)
instance - 3
DAY - TUESDAY
time -10 am

NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'TUESDAY') + (7 * (3 - 1)) + 10/24

i.e. NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'TUESDAY') + 14 + 10/24
SELECT NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'TUESDAY') + (7 * (3 - 1)) + 10/24
FROM DUAL

SELECT NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'TUESDAY') + 14 + 10/24
FROM DUAL
                                    
1:
2:
3:
4:
5:

Select allOpen in new window






Example 2 - 1st Monday of the month at 2 pm


date - TRUNC(SYSDATE)
instance - 1
DAY - MONDAY
time -2 pm

NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'MONDAY') + (7 * (1 - 1)) + 14/24

i.e. NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'MONDAY') + 14/24
SELECT NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'MONDAY') + (7 * (1 - 1)) + 14/24
FROM DUAL

SELECT NEXT_DAY(LAST_DAY(trunc(SYSDATE)), 'MONDAY') + 14/24
FROM DUAL
                                    
1:
2:
3:
4:
5:

Select allOpen in new window

Asked On
2011-06-03 at 00:31:19ID5969
Tags

Oracle

,

SQL

,

PL/SQL

Topic

Oracle Database

Views
904

Comments

Expert Comment

by: wasimibm on 2012-01-02 at 10:07:47ID: 34071

nice article..!!!!

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top Oracle Database Experts

  1. slightwv

    811,605

    Sage

    12,800 points yesterday

    Profile
    Rank: Genius
  2. sdstuber

    578,296

    Sage

    3,540 points yesterday

    Profile
    Rank: Genius
  3. wasimibm

    159,939

    Guru

    2,100 points yesterday

    Profile
    Rank: Guru
  4. tosse

    83,962

    Master

    1,510 points yesterday

    Profile
    Rank: Master
  5. dvz

    77,992

    Master

    900 points yesterday

    Profile
    Rank: Sage
  6. flow01

    70,666

    Master

    0 points yesterday

    Profile
    Rank: Sage
  7. OP_Zaharin

    66,395

    Master

    0 points yesterday

    Profile
    Rank: Sage
  8. Geert_Gruwez

    66,198

    Master

    800 points yesterday

    Profile
    Rank: Genius
  9. awking00

    63,850

    Master

    0 points yesterday

    Profile
    Rank: Genius
  10. MikeOM_DBA

    55,954

    Master

    10 points yesterday

    Profile
    Rank: Genius
  11. johnsone

    46,104

    0 points yesterday

    Profile
    Rank: Genius
  12. schwertner

    43,375

    0 points yesterday

    Profile
    Rank: Genius
  13. slobaray

    42,921

    20 points yesterday

    Profile
    Rank: Master
  14. Bajwa

    35,334

    1,000 points yesterday

    Profile
  15. gatorvip

    33,868

    0 points yesterday

    Profile
    Rank: Sage
  16. praveencpk

    33,355

    0 points yesterday

    Profile
    Rank: Master
  17. sujith80

    30,896

    0 points yesterday

    Profile
    Rank: Genius
  18. sventhan

    30,548

    0 points yesterday

    Profile
    Rank: Sage
  19. markgeer

    29,292

    0 points yesterday

    Profile
    Rank: Genius
  20. paquicuba

    26,860

    0 points yesterday

    Profile
    Rank: Genius
  21. HainKurt

    24,922

    0 points yesterday

    Profile
    Rank: Genius
  22. Milleniumaire

    20,300

    0 points yesterday

    Profile
    Rank: Sage
  23. ytarkan

    17,352

    0 points yesterday

    Profile
  24. mwvisa1

    15,600

    0 points yesterday

    Profile
    Rank: Genius
  25. angelIII

    14,509

    0 points yesterday

    Profile
    Rank: Elite

Hall Of Fame