Introduction
Python's datetime module provides datetime.now() to get the current date and time, with .year and .month attributes to extract the year and month as integers. For the current date only (without time), use date.today(). These values are commonly used for file naming, log timestamps, report headers, filtering data, and generating date ranges.
Getting Current Year and Month
1from datetime import datetime, date
2
3# Using datetime.now()
4now = datetime.now()
5print(now.year) # 2026
6print(now.month) # 3
7print(now.day) # 2
8
9# Using date.today() — lighter, no time component
10today = date.today()
11print(today.year) # 2026
12print(today.month) # 3
13print(today.day) # 2
1from datetime import datetime
2
3now = datetime.now()
4
5# strftime formatting
6print(now.strftime("%Y")) # "2026" — 4-digit year
7print(now.strftime("%y")) # "26" — 2-digit year
8print(now.strftime("%m")) # "03" — zero-padded month
9print(now.strftime("%B")) # "March" — full month name
10print(now.strftime("%b")) # "Mar" — abbreviated month name
11print(now.strftime("%Y-%m")) # "2026-03"
12print(now.strftime("%B %Y")) # "March 2026"
13
14# f-string formatting
15year = now.year
16month = now.month
17print(f"{year}-{month:02d}") # "2026-03" — zero-padded
Common Use Cases
File Naming
1from datetime import datetime
2
3now = datetime.now()
4filename = f"report_{now.year}_{now.month:02d}.csv"
5print(filename) # "report_2026_03.csv"
6
7log_dir = f"logs/{now.year}/{now.month:02d}/"
8print(log_dir) # "logs/2026/03/"
Filtering Data by Current Month
1from datetime import datetime, date
2
3today = date.today()
4current_year = today.year
5current_month = today.month
6
7# Filter a list of records
8orders = [
9 {"id": 1, "date": date(2026, 3, 1), "amount": 100},
10 {"id": 2, "date": date(2026, 2, 15), "amount": 200},
11 {"id": 3, "date": date(2026, 3, 15), "amount": 150},
12]
13
14this_month = [
15 o for o in orders
16 if o["date"].year == current_year and o["date"].month == current_month
17]
18print(this_month) # Orders 1 and 3
First and Last Day of Current Month
1from datetime import date
2import calendar
3
4today = date.today()
5
6# First day of current month
7first_day = today.replace(day=1)
8print(first_day) # 2026-03-01
9
10# Last day of current month
11last_day_num = calendar.monthrange(today.year, today.month)[1]
12last_day = today.replace(day=last_day_num)
13print(last_day) # 2026-03-31
14
15# First day of next month
16if today.month == 12:
17 next_month_first = date(today.year + 1, 1, 1)
18else:
19 next_month_first = date(today.year, today.month + 1, 1)
20print(next_month_first) # 2026-04-01
Generating Month Ranges
1from datetime import date
2import calendar
3
4def months_in_year(year):
5 """Generate (year, month) tuples for all months in a year."""
6 return [(year, m) for m in range(1, 13)]
7
8def months_between(start_year, start_month, end_year, end_month):
9 """Generate (year, month) tuples between two dates."""
10 months = []
11 year, month = start_year, start_month
12 while (year, month) <= (end_year, end_month):
13 months.append((year, month))
14 if month == 12:
15 year += 1
16 month = 1
17 else:
18 month += 1
19 return months
20
21print(months_between(2025, 10, 2026, 3))
22# [(2025, 10), (2025, 11), (2025, 12), (2026, 1), (2026, 2), (2026, 3)]
With Timezone Awareness
1from datetime import datetime, timezone
2from zoneinfo import ZoneInfo
3
4# UTC
5utc_now = datetime.now(timezone.utc)
6print(f"UTC: {utc_now.year}-{utc_now.month:02d}")
7
8# Specific timezone
9tokyo = datetime.now(ZoneInfo("Asia/Tokyo"))
10print(f"Tokyo: {tokyo.year}-{tokyo.month:02d}")
11
12# Near midnight, year/month may differ between timezones
13ny = datetime.now(ZoneInfo("America/New_York"))
14print(f"New York: {ny.year}-{ny.month:02d}")
Using pandas
1import pandas as pd
2
3# Current timestamp
4now = pd.Timestamp.now()
5print(now.year) # 2026
6print(now.month) # 3
7print(now.month_name()) # "March"
8
9# Period — represents an entire month
10current_period = pd.Period(now, freq="M")
11print(current_period) # 2026-03
12print(current_period.year) # 2026
13print(current_period.month) # 3
14
15# Filter DataFrame by current year/month
16df = pd.DataFrame({
17 "date": pd.date_range("2026-01-01", periods=90, freq="D"),
18 "value": range(90),
19})
20current = df[
21 (df["date"].dt.year == now.year) &
22 (df["date"].dt.month == now.month)
23]
Common Pitfalls
Using datetime.now() without timezone in production: datetime.now() returns the system's local time, which varies between servers. In production, always use datetime.now(timezone.utc) for consistent timestamps. The year/month can differ near midnight UTC depending on the server's timezone.
Assuming months are zero-indexed: Unlike JavaScript (where January is 0), Python months are 1-indexed (January is 1, December is 12). There is no need to add 1 to .month for display.
Hardcoding days per month: Not all months have 31 days, and February varies by year. Use calendar.monthrange(year, month) to get the correct number of days. Manually setting day=31 for months with 30 days raises ValueError.
String formatting without zero-padding: str(now.month) gives "3" for March, not "03". Use f"{now.month:02d}" or now.strftime("%m") for zero-padded month numbers in filenames and date strings.
Confusing date.today() with datetime.now(): date.today() returns a date object (no time). datetime.now() returns a datetime object (has time). Both have .year and .month, but date objects cannot be used where datetime is expected without conversion.
Summary
Use datetime.now().year and datetime.now().month for the current year and month as integers
Use date.today() for a lighter alternative when you do not need the time component
Format with strftime("%Y-%m") for strings or f"{month:02d}" for zero-padded numbers
Use calendar.monthrange(year, month) to get the last day of a month
Always use timezone-aware datetimes (datetime.now(timezone.utc)) in production
Python months are 1-indexed (January=1, December=12)