Introduction
Adding hours to the current time in Python uses datetime.now() combined with timedelta(hours=n). The timedelta object represents a duration, and adding it to a datetime produces a new datetime shifted by that amount. This handles day boundaries, month boundaries, and DST transitions correctly when used with timezone-aware datetimes.
Basic Usage with datetime and timedelta
1from datetime import datetime, timedelta
2
3now = datetime.now()
4print(f"Current time: {now}")
5# Current time: 2025-09-24 14:30:00.123456
6
7# Add 3 hours
8future = now + timedelta(hours=3)
9print(f"3 hours later: {future}")
10# 3 hours later: 2025-09-24 17:30:00.123456
11
12# Add fractional hours
13half_hour_later = now + timedelta(hours=0.5)
14print(f"30 minutes later: {half_hour_later}")
15# 30 minutes later: 2025-09-24 15:00:00.123456
16
17# Subtract hours
18past = now - timedelta(hours=5)
19print(f"5 hours ago: {past}")
20# 5 hours ago: 2025-09-24 09:30:00.123456
Crossing Day Boundaries
timedelta handles day rollovers automatically:
1from datetime import datetime, timedelta
2
3late_night = datetime(2025, 9, 24, 23, 0, 0) # 11:00 PM
4print(late_night + timedelta(hours=3))
5# 2025-09-25 02:00:00 (correctly rolls to the next day)
6
7end_of_month = datetime(2025, 1, 31, 22, 0, 0)
8print(end_of_month + timedelta(hours=5))
9# 2025-02-01 03:00:00 (correctly rolls to February)
Timezone-Aware Datetimes
Use zoneinfo (Python 3.9+) for timezone handling:
1from datetime import datetime, timedelta
2from zoneinfo import ZoneInfo
3
4# Current time in a specific timezone
5ny_time = datetime.now(ZoneInfo("America/New_York"))
6print(f"New York: {ny_time}")
7
8# Add 5 hours
9later = ny_time + timedelta(hours=5)
10print(f"5 hours later: {later}")
11
12# Convert between timezones
13tokyo_time = later.astimezone(ZoneInfo("Asia/Tokyo"))
14print(f"Tokyo time: {tokyo_time}")
Using pytz (Pre-Python 3.9)
1from datetime import datetime, timedelta
2import pytz
3
4eastern = pytz.timezone("US/Eastern")
5now = datetime.now(eastern)
6print(f"Eastern: {now}")
7
8# Add hours
9later = now + timedelta(hours=6)
10print(f"6 hours later: {later}")
11
12# Normalize after arithmetic (handles DST transitions)
13later_normalized = eastern.normalize(later)
14print(f"Normalized: {later_normalized}")
pytz.normalize() adjusts the UTC offset if the addition crossed a DST boundary.
Using dateutil.relativedelta
relativedelta handles more complex date arithmetic:
1from datetime import datetime
2from dateutil.relativedelta import relativedelta
3
4now = datetime.now()
5
6# Add hours with relativedelta
7later = now + relativedelta(hours=8)
8print(later)
9
10# Combine with other units
11combined = now + relativedelta(hours=2, minutes=30, seconds=15)
12print(combined)
13
14# relativedelta can also add months and years (timedelta cannot)
15next_month = now + relativedelta(months=1, hours=3)
16print(next_month)
Using pandas Timestamp
1import pandas as pd
2
3now = pd.Timestamp.now()
4print(f"Now: {now}")
5
6# Add hours using pd.Timedelta
7later = now + pd.Timedelta(hours=4)
8print(f"4 hours later: {later}")
9
10# Or use the offset
11later = now + pd.DateOffset(hours=4)
12print(f"4 hours later: {later}")
13
14# Works with Series too
15times = pd.Series(pd.date_range("2025-01-01", periods=5, freq="h"))
16shifted = times + pd.Timedelta(hours=3)
17print(shifted)
1from datetime import datetime, timedelta
2
3now = datetime.now()
4future = now + timedelta(hours=2, minutes=30)
5
6# Standard format strings
7print(future.strftime("%Y-%m-%d %H:%M:%S")) # 2025-09-24 17:00:00
8print(future.strftime("%I:%M %p")) # 05:00 PM
9print(future.strftime("%B %d, %Y at %H:%M")) # September 24, 2025 at 17:00
10
11# ISO format
12print(future.isoformat()) # 2025-09-24T17:00:00.123456
Calculating Hours Between Two Times
1from datetime import datetime
2
3start = datetime(2025, 9, 24, 9, 0)
4end = datetime(2025, 9, 25, 14, 30)
5
6diff = end - start
7hours = diff.total_seconds() / 3600
8print(f"Difference: {hours} hours") # 29.5 hours
Working with time Objects (Not datetime)
1from datetime import datetime, time, timedelta
2
3# time objects don't support arithmetic directly
4t = time(14, 30, 0) # 2:30 PM
5
6# Workaround: combine with a date, add hours, extract time
7dt = datetime.combine(datetime.today(), t)
8result = (dt + timedelta(hours=3)).time()
9print(result) # 17:30:00
10
11# Be careful: this wraps around midnight
12late = time(23, 0, 0)
13dt = datetime.combine(datetime.today(), late)
14result = dt + timedelta(hours=3)
15print(result.time()) # 02:00:00
16print(result.date()) # Next day, check if you need this
Common Pitfalls
Naive vs aware datetimes: datetime.now() returns a naive datetime (no timezone). Mixing naive and aware datetimes raises TypeError. Pick one and stay consistent. Use datetime.now(tz) for aware datetimes.
DST transitions: Adding 2 hours across a DST boundary may shift the clock by 1 or 3 hours in wall-clock time. Use timezone-aware datetimes and normalize() (pytz) to handle this correctly.
time objects cannot add hours: time(14, 0) + timedelta(hours=1) raises TypeError. Combine with a date first, then extract .time() from the result.
Floating-point hours: timedelta(hours=1.5) works correctly (1 hour 30 minutes), but avoid accumulating floating-point errors with many additions. Use timedelta(hours=1, minutes=30) for precision.
UTC vs local time: datetime.utcnow() returns a naive datetime in UTC. It is not timezone-aware. Use datetime.now(timezone.utc) instead (Python 3.2+).
Summary
Use datetime.now() + timedelta(hours=n) to add hours to the current time
timedelta handles day, month, and year boundaries automatically
Use zoneinfo.ZoneInfo (Python 3.9+) or pytz for timezone-aware arithmetic
dateutil.relativedelta supports adding months and years alongside hours
Format results with strftime() or .isoformat()
Always use timezone-aware datetimes in production to avoid DST and UTC issues