Skip to content

Period Guide

The Period class provides semantic time period operations using named constants for more readable and maintainable datetime code.

Overview

Instead of writing dt.add(months=1), you can write Period.MONTH.add_to(dt) for clearer intent and better readability.

Available Periods

from carbonic import Period

# Available period constants
Period.MINUTE    # 1 minute
Period.HOUR      # 1 hour
Period.DAY       # 1 day
Period.WEEK      # 1 week
Period.MONTH     # 1 month
Period.QUARTER   # 1 quarter (3 months)
Period.YEAR      # 1 year

Basic Usage

from carbonic import DateTime, Date, Period

dt = DateTime(2024, 6, 15, 14, 30)
date = Date(2024, 6, 15)

# Add periods
next_month = Period.MONTH.add_to(dt)        # 2024-07-15T14:30:00
next_week = Period.WEEK.add_to(date)        # 2024-06-22
next_quarter = Period.QUARTER.add_to(date)  # 2024-09-15

# Subtract periods
last_year = Period.YEAR.subtract_from(dt)   # 2023-06-15T14:30:00
yesterday = Period.DAY.subtract_from(date)  # 2024-06-14

Multiple Units

from carbonic import Date, Period

date = Date(2024, 6, 15)

# Add multiple periods
five_days_later = Period.DAY.add_to(date, count=5)     # 2024-06-20
three_months_ago = Period.MONTH.subtract_from(date, count=3)  # 2024-03-15
two_years_future = Period.YEAR.add_to(date, count=2)   # 2026-06-15

Period Anchoring

Find the start or end of a period:

from carbonic import DateTime, Period

dt = DateTime(2024, 6, 15, 14, 30, 45)

# Start of periods
start_of_week = Period.WEEK.start_of(dt)      # Monday 00:00:00
start_of_month = Period.MONTH.start_of(dt)    # June 1st 00:00:00
start_of_quarter = Period.QUARTER.start_of(dt) # April 1st 00:00:00
start_of_year = Period.YEAR.start_of(dt)      # January 1st 00:00:00

# End of periods
end_of_week = Period.WEEK.end_of(dt)          # Sunday 23:59:59.999999
end_of_month = Period.MONTH.end_of(dt)        # June 30th 23:59:59.999999
end_of_quarter = Period.QUARTER.end_of(dt)   # June 30th 23:59:59.999999
end_of_year = Period.YEAR.end_of(dt)          # December 31st 23:59:59.999999

Time Periods (DateTime Only)

Minute and hour periods work only with DateTime objects:

from carbonic import DateTime, Period

dt = DateTime(2024, 6, 15, 14, 30, 45)

# Time-based periods
next_minute = Period.MINUTE.add_to(dt)        # 2024-06-15T14:31:45
start_of_hour = Period.HOUR.start_of(dt)      # 2024-06-15T14:00:00
end_of_minute = Period.MINUTE.end_of(dt)      # 2024-06-15T14:30:59.999999

Comparison with Direct Methods

Both approaches work - choose based on your preference:

from carbonic import DateTime, Period

dt = DateTime(2024, 6, 15, 14, 30)

# Using Period (semantic)
result1 = Period.MONTH.add_to(dt)
result2 = Period.WEEK.start_of(dt)

# Using direct methods (concise)
result3 = dt.add(months=1)
result4 = dt.start_of("week")

# Both produce identical results
assert result1 == result3
assert result2 == result4

Use Cases

When to Use Periods

Good for: - Configuration: BILLING_PERIOD = Period.MONTH - Business logic: if payment_due.add_to(Period.QUARTER): - Templates: More readable in configuration files - Domain modeling: Express business concepts clearly

Example:

from carbonic import Date, Period

class SubscriptionPlan:
    def __init__(self, billing_period: Period):
        self.billing_period = billing_period

    def next_billing_date(self, start_date: Date) -> Date:
        return self.billing_period.add_to(start_date)

# Usage
monthly_plan = SubscriptionPlan(Period.MONTH)
quarterly_plan = SubscriptionPlan(Period.QUARTER)

start = Date(2024, 1, 15)
next_monthly = monthly_plan.next_billing_date(start)    # 2024-02-15
next_quarterly = quarterly_plan.next_billing_date(start) # 2024-04-15

When to Use Direct Methods

Good for: - Simple operations: dt.add(days=7) - Dynamic counts: dt.add(months=user_input) - Method chaining: dt.add(days=1).start_of("month")

Working with Dates vs DateTimes

from carbonic import DateTime, Date, Period

# Works with both Date and DateTime
date = Date(2024, 6, 15)
dt = DateTime(2024, 6, 15, 14, 30)

# Calendar periods work with both
Period.DAY.add_to(date)     # Returns Date
Period.DAY.add_to(dt)       # Returns DateTime

Period.MONTH.add_to(date)   # Returns Date
Period.MONTH.add_to(dt)     # Returns DateTime

# Time periods only work with DateTime
Period.HOUR.add_to(dt)      # ✅ Works - Returns DateTime
# Period.HOUR.add_to(date)  # ❌ Would raise error

Error Handling

from carbonic import Date, Period

date = Date(2024, 6, 15)

# This will raise an error - time periods require DateTime
try:
    Period.MINUTE.add_to(date)  # ❌ Error
except ValueError as e:
    print(f"Error: {e}")  # Time periods require DateTime objects

Performance Notes

Period operations have the same performance characteristics as direct method calls - they're just a different API for the same underlying functionality.

from carbonic import DateTime, Period

dt = DateTime(2024, 6, 15, 14, 30)

# These are equivalent in performance:
result1 = Period.MONTH.add_to(dt)  # Period API
result2 = dt.add(months=1)         # Direct API

See Also