NSE trading calendar with holidays, date arithmetic, flexible formatting
Project description
🗓️ nse-calendar
📦 NSE (National Stock Exchange of India) trading calendar for Python.
Features: Holiday detection, trading day arithmetic, flexible date parsing/formatting, and seamless Pandas integration. Zero mandatory dependencies.
🔍 Data Coverage
The package includes one of the most comprehensive publicly available NSE holiday datasets, covering trading holidays from 1996 onwards and updated annually using official NSE circulars and archives.
| Year Range | Status | Source |
|---|---|---|
| 1996–2009 | ✅ Available | NSE historical archives |
| 2010–2025 | ✅ Available | NSE official annual circulars |
| 2026 | ✅ Available | NSE official annual circular |
| 2027 and beyond | ⏳ Added each December | NSE official annual circular |
⚡ Installation
pip install nse-calendar
Note:
pandasandrequestsare optional dependencies. The library works flawlessly with Python's standard library alone.
🚀 Quick Start
import nse_calendar as nse
# Is this a trading day?
nse.is_nse_holiday("2026-01-26") # True (Republic Day)
nse.is_nse_holiday("2026-05-25") # False
# Move forward by trading days
nse.add_trading_days("2026-01-23", 1) # 2026-01-27
# Count trading days in a range
nse.trading_days_between("2026-01-01", "2026-01-31")
# Parse and format dates easily
d = nse.parse_date("25-May-2026")
nse.format_date(d, "dd/mm/yyyy") # '25/05/2026'
nse.format_date(d, "dd Month yyyy") # '25 May 2026'
🛠️ API Reference
1. Holiday Checks
is_nse_holiday(date) -> bool
Returns True if the date is an NSE trading holiday or a weekend. Returns False for normal trading days.
nse.is_nse_holiday("2026-01-26") # True - Republic Day
nse.is_nse_holiday("2026-05-23") # True - Saturday
nse.is_nse_holiday("2026-05-25") # False - Monday, normal session
nse.is_nse_holiday(datetime.date(2026, 12, 25)) # True - Christmas
get_holidays(year) -> list[dict]
Returns all NSE holidays for a given year as a list of dictionaries. Returns an empty list if the year is not present in the dataset.
nse.get_holidays(2026)
# Output:
# [
# {"date": "2026-01-26", "description": "Republic Day"},
# {"date": "2026-03-03", "description": "Maha Shivaratri"},
# ...
# ]
len(nse.get_holidays(2026)) # 16
nse.get_holidays(1995) # []
2. Special Sessions
Special sessions, such as Muhurat Trading on Diwali, override normal weekday and weekend rules. They are considered trading days even if they fall on a weekend.
is_special_session(date) -> bool
Returns True if the date is a special trading session.
nse.is_special_session("2026-11-08") # True (Diwali Lakshmi Puja)
nse.is_special_session("2026-01-26") # False
get_special_sessions(year) -> list[dict]
Returns all special trading sessions for a given year.
nse.get_special_sessions(2026)
# Output:
# [
# {"date": "2026-11-08", "description": "Diwali Lakshmi Puja"}
# ]
3. Trading Day Arithmetic
add_trading_days(date, n) -> datetime.date
Advances a date by exactly n trading days, skipping weekends and NSE holidays. A negative value of n moves backward.
nse.add_trading_days("2026-01-23", 1) # date(2026, 1, 27)
nse.add_trading_days("2026-05-25", 5) # date(2026, 6, 1)
nse.add_trading_days("2026-05-25", -3) # date(2026, 5, 20)
subtract_trading_days(date, n) -> datetime.date
Moves a date backward by exactly n trading days.
nse.subtract_trading_days("2026-01-27", 1) # date(2026, 1, 23)
nse.subtract_trading_days("2026-06-01", 5) # date(2026, 5, 25)
trading_days_between(start, end, inclusive="both") -> int
Counts trading days between two dates. The order of start and end does not matter.
inclusive option |
Count Start? | Count End? |
|---|---|---|
"both" |
Yes | Yes |
"left" |
Yes | No |
"right" |
No | Yes |
"neither" |
No | No |
nse.trading_days_between("2026-06-01", "2026-06-05") # 5
nse.trading_days_between("2026-06-01", "2026-06-05", inclusive="neither") # 3
nse.trading_days_between("2026-01-22", "2026-01-30") # 5
next_trading_day(date) -> datetime.date | prev_trading_day(date)
Returns the next or previous strict trading day.
nse.next_trading_day("2026-01-26") # date(2026, 1, 27)
nse.prev_trading_day("2026-01-27") # date(2026, 1, 23)
nearest_trading_day(date, direction="forward") -> datetime.date
If the supplied date is already a trading day, it returns it unchanged. Otherwise, it finds the nearest one based on direction ("forward" or "backward").
nse.nearest_trading_day("2026-05-25") # date(2026, 5, 25)
nse.nearest_trading_day("2026-01-26") # date(2026, 1, 27)
nse.nearest_trading_day("2026-01-26", direction="backward") # date(2026, 1, 23)
4. Date Parsing & Formatting
parse_date(value) -> datetime.date
Converts strings ("2026-05-25", "25-May-26", "May 25, 2026"), Unix timestamps, or Pandas/Python datetimes smoothly into a datetime.date object.
nse.parse_date("25-May-2026") # date(2026, 5, 25)
nse.parse_date(1748131200) # date from Unix timestamp
format_date(date, fmt) -> str
Formats a date using human-readable tokens (dd-mm-yyyy, dd Month yyyy, etc.) or any standard % strftime pattern.
nse.format_date("2026-05-25", "dd Month yyyy") # '25 May 2026'
nse.format_date("2026-05-25", "%A, %d %B %Y") # 'Monday, 25 May 2026'
5. Pandas Integration
resolve_dataframe(df, col, output_col=None, fmt="dd-mm-yyyy") -> pd.DataFrame
Parses mixed-format data columns, formats them uniformly, and returns helper flags without modifying your original DataFrame.
| Added Column | Type | Description |
|---|---|---|
{col} or output_col |
str |
Reformatted dates using fmt |
{col}_is_holiday |
bool |
True if an NSE holiday or weekend |
{col}_is_weekend |
bool |
True if a Saturday or Sunday |
import pandas as pd
import nse_calendar as nse
df = pd.DataFrame({"trade_date": ["2026-01-26", "25-05-2026", "2026-05-23"]})
out = nse.resolve_dataframe(df, "trade_date", fmt="dd-mm-yyyy")
🔄 Data Control & Management
The library uses a smart two-layer data loading strategy:
- Local Cache: Stored at
~/.cache/nse_calendar/holidays.json(Valid for 30 days). - Remote Source: Fetched from GitHub if the cache expires or is missing.
nse.refresh_holidays(force=True) # Manually force a fresh fetch from remote
nse.get_data_source_info() # View active cache metadata status
🤝 Contributing
Spot a missing holiday or a wrong date? Please open an issue and include the official NSE circular reference so the dataset can be updated for everyone!
📄 License
MIT License. See LICENSE for details.
Maintained with ❤️ by Kartik Kasat*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nse_calendar-1.0.0.tar.gz.
File metadata
- Download URL: nse_calendar-1.0.0.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c49b4a936afed17faac116accfd04a29300fe31912a9cf9c683a677d22b83bfa
|
|
| MD5 |
dadf3b8d514d56bf7e9711bfdae9c7d9
|
|
| BLAKE2b-256 |
1be544b84123f1205dd949391f284b7ba28f00a0d9c9dd0b91c1e92ce221a3f2
|
File details
Details for the file nse_calendar-1.0.0-py3-none-any.whl.
File metadata
- Download URL: nse_calendar-1.0.0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92deaeade43f144b55664c8bb2998c2356a23c824711162c6b05f90afc4beda6
|
|
| MD5 |
d006a813b9f3f0586ccc71358539a9e7
|
|
| BLAKE2b-256 |
bf57b25f809aed586f6821c06e92496a25eb547544b2d40716b85a93edefbd8b
|