仅给定时间时获取区间上下限的更优方法
Hey there! Precomputing every possible interval and stuffing them into a dictionary works, but it’s far from the most efficient approach—especially when you need to support custom interval types. Let’s walk through a smarter, on-the-fly method that’s memory-efficient, flexible, and way easier to maintain.
Core Idea
Instead of pre-storing intervals, we calculate the lower and upper bounds dynamically using datetime arithmetic. The lower bound is always the start of the current interval (truncating the given datetime to fit the interval’s granularity), and the upper bound is just the lower bound plus the interval’s duration.
Example Implementation (Python)
Here’s a reusable function that handles standard intervals and lets you add custom ones with zero extra pre-work:
from datetime import datetime, timedelta def get_interval_bounds(target_dt: datetime, interval_type: str): # Map interval names to their timedelta durations—add custom entries here! interval_defs = { "hour": timedelta(hours=1), "30min": timedelta(minutes=30), "15min": timedelta(minutes=15), "45min": timedelta(minutes=45), "day": timedelta(days=1) } if interval_type not in interval_defs: raise ValueError(f"Unsupported interval: {interval_type}. Try one of: {list(interval_defs.keys())}") interval = interval_defs[interval_type] lower_bound = None # Calculate lower bound by truncating the datetime to the interval start if interval_type == "hour": lower_bound = target_dt.replace(minute=0, second=0, microsecond=0) elif interval_type in ["30min", "15min", "45min"]: total_minutes = target_dt.hour * 60 + target_dt.minute minutes_into_interval = total_minutes % int(interval.total_seconds() // 60) lower_bound = target_dt - timedelta( minutes=minutes_into_interval, seconds=target_dt.second, microseconds=target_dt.microsecond ) elif interval_type == "day": lower_bound = target_dt.replace(hour=0, minute=0, second=0, microsecond=0) # Upper bound is simply lower bound plus the interval duration upper_bound = lower_bound + interval return (lower_bound, upper_bound) # Test with your example time test_time = datetime(2024, 5, 20, 12, 5, 30) print("Hourly interval:", get_interval_bounds(test_time, "hour")) # Output: (datetime.datetime(2024, 5, 20, 12, 0), datetime.datetime(2024, 5, 20, 13, 0)) print("30-minute interval:", get_interval_bounds(test_time, "30min")) # Output: (datetime.datetime(2024, 5, 20, 12, 0), datetime.datetime(2024, 5, 20, 12, 30)) print("15-minute interval:", get_interval_bounds(test_time, "15min")) # Output: (datetime.datetime(2024, 5, 20, 12, 0), datetime.datetime(2024, 5, 20, 12, 15))
Why This Beats Precomputed Dictionaries
- Memory-friendly: No need to store thousands of interval entries—calculations happen in real time with minimal overhead.
- Flexible: Adding a custom interval (like "2hour" or "10min") is as simple as adding a new line to
interval_defs—no precomputation required. - Scalable: Works for any datetime (past, present, future) instead of being limited to a pre-defined range.
- Low maintenance: No need to update or rebuild a dictionary when your interval needs change.
Handling Variable-Length Intervals
For trickier intervals like monthly or quarterly (which don’t have fixed durations), use dateutil’s relativedelta to handle variable-length gaps:
from dateutil.relativedelta import relativedelta def get_quarterly_interval(target_dt: datetime): # Calculate the start of the current quarter quarter_start_month = ((target_dt.month - 1) // 3) * 3 + 1 lower_bound = target_dt.replace(month=quarter_start_month, day=1, hour=0, minute=0, second=0, microsecond=0) upper_bound = lower_bound + relativedelta(months=3) return (lower_bound, upper_bound)
This approach keeps your code clean, adaptable, and avoids the clutter of precomputed interval dictionaries.
内容的提问来源于stack exchange,提问作者ashwathmabiyan

