Oracle CALENDAR_ Functions

Name the quarter, month, or week of a date, find the first and last day of any period, and move dates by whole periods in one call.

Reports constantly need the name of a period (Q1-2026, MAR-2026, week 11), its first and last day, or a date a few periods later. Oracle AI Database 26ai adds a family of CALENDAR_ functions that answer these directly for the Gregorian calendar, so you no longer build them from TRUNC, TO_CHAR, ADD_MONTHS, and LAST_DAY.

Code for This Guide

The main example is in the examples/date-functions folder of the Oracle Database 26ai code repository on GitHub, with its output. It queries NIMBUS, the sample schema of a fictional airline, which you can install with the scripts in the setup/nimbus folder.

It comes from Oracle Database 26ai SQL and PL/SQL Book.

The Family

Syntax:

calendar_year(dtexpr [, fmt [, nlsparam]])   -- and the other members below
FunctionsReturn
CALENDAR_YEAR, _QUARTER, _MONTH, _WEEK, _DAYThe name of the period a date is in, such as Q1-2026
CALENDAR_YEAR_NUMBERThe year as a number
CALENDAR_DAY_OF_WEEK, _OF_MONTH, _OF_QUARTER, _OF_YEARThe day's number within a period
CALENDAR_WEEK_OF_YEAR, CALENDAR_MONTH_OF_QUARTER, _OF_YEAR, CALENDAR_QUARTER_OF_YEARA period's number within a larger period
CALENDAR_YEAR_START_DATE, _QUARTER_, _MONTH_, _WEEK_START_DATE, and the _END_DATE versionsThe first or last day of a period
CALENDAR_ADD_YEARS, _QUARTERS, _MONTHS, _WEEKS, _DAYSThe date moved by a number of periods
CALENDAR_SINCEThe time since a date in words

The period names have their own formats and ignore NLS_DATE_FORMAT; an optional format argument changes them.

Names, Boundaries, and Arithmetic

The first query names the periods of 15 March 2026; the second finds its quarter's start and end, its day and week of the year, and the date two months later.

Example:

select calendar_year(d) as year, calendar_quarter(d) as quarter,
       calendar_month(d) as month, calendar_week(d) as week, calendar_day(d) as day
from   (select date '2026-03-15' as d);

select calendar_quarter_start_date(d) as q_start, calendar_quarter_end_date(d) as q_end,
       calendar_day_of_year(d) as day_of_year, calendar_week_of_year(d) as week_of_year,
       calendar_add_months(d, 2) as plus_2_months
from   (select date '2026-03-15' as d);

Output:

YEAR    QUARTER    MONTH       WEEK        DAY
_______ __________ ___________ ___________ ______________
2026    Q1-2026    MAR-2026    W11-2026    15-MAR-2026

Q_START        Q_END             DAY_OF_YEAR    WEEK_OF_YEAR PLUS_2_MONTHS
______________ ______________ ______________ _______________ ________________
01-JAN-2026    31-MAR-2026                74              11 15-MAY-2026

More Members

Example:

select calendar_month_start_date(d) as month_start,
       calendar_month_end_date(d)   as month_end,
       calendar_week_start_date(d)  as week_start,
       calendar_add_weeks(d, 3)     as plus_3_weeks,
       calendar_quarter_of_year(d)  as quarter_no
from   (select date '2026-03-15' as d);

-- tickets per calendar quarter and month, named by the calendar functions
select calendar_quarter(b.booked_at) as quarter, calendar_month(b.booked_at) as month,
       count(*) as bookings
from   bookings b
group  by all
order  by min(b.booked_at);

Output:

MONTH_START    MONTH_END      WEEK_START     PLUS_3_WEEKS       QUARTER_NO
______________ ______________ ______________ _______________ _____________
01-MAR-2026    31-MAR-2026    12-MAR-2026    05-APR-2026                 1

QUARTER    MONTH          BOOKINGS
__________ ___________ ___________
Q4-2025    OCT-2025              7
Q4-2025    NOV-2025             81
Q4-2025    DEC-2025            164
Q1-2026    JAN-2026            222
Q1-2026    FEB-2026            154
Q1-2026    MAR-2026             72

6 rows selected.

Calendar weeks are counted from 1 January, so they start on that day's weekday: in 2026 a Thursday, which is why the week of 15 March starts on 12 March. The second query groups bookings by the quarter and month names, ready to print in a report, and orders the groups chronologically with min(booked_at).

Things to Know

  • FISCAL_ functions have the same members for a year that starts on another day, and RETAIL_ functions for the 4-5-4 retail calendar.
  • For ISO weeks that start on Monday, use the IW and IYYY format elements of TO_CHAR.
  • Period names sort as text, not chronologically; order by a date or a number column instead.

Related Guides

Conclusion

The CALENDAR_ functions name the year, quarter, month, week, and day a date falls in, return the first and last day of each period, number days and periods within larger ones, and move dates by whole periods. They replace a lot of hand-built date logic in reports.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted