or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-date-time-range

DateTimeRange is a Python library to handle a time range, providing operations for checking containment, intersection, iteration, and other datetime range manipulations.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/datetimerange@2.3.x

To install, run

npx @tessl/cli install tessl/pypi-date-time-range@2.3.0

index.mddocs/

DateTimeRange

DateTimeRange is a Python library to handle a time range. It provides comprehensive functionality for working with datetime intervals including checking containment, calculating intersections and unions, truncating ranges, splitting ranges, and iterating through time periods with custom intervals.

Package Information

  • Package Name: DateTimeRange
  • Language: Python
  • Installation: pip install DateTimeRange
  • Requirements: Python 3.9+

Core Imports

from datetimerange import DateTimeRange

Basic Usage

import datetime
from datetimerange import DateTimeRange

# Create a time range from string representations
time_range = DateTimeRange("2015-03-22T10:00:00+0900", "2015-03-22T10:10:00+0900")
print(time_range)  # 2015-03-22T10:00:00+0900 - 2015-03-22T10:10:00+0900

# Create from datetime objects
start = datetime.datetime(2015, 3, 22, 10, 0, 0)
end = datetime.datetime(2015, 3, 22, 10, 10, 0)
time_range = DateTimeRange(start, end)

# Check if a time is within the range
check_time = "2015-03-22T10:05:00+0900"
print(check_time in time_range)  # True

# Get intersection of two ranges
range1 = DateTimeRange("2015-03-22T10:00:00+0900", "2015-03-22T10:10:00+0900")
range2 = DateTimeRange("2015-03-22T10:05:00+0900", "2015-03-22T10:15:00+0900")
intersection = range1.intersection(range2)
print(intersection)  # 2015-03-22T10:05:00+0900 - 2015-03-22T10:10:00+0900

# Iterate through time range with step intervals
import datetime
for time_point in time_range.range(datetime.timedelta(minutes=2)):
    print(time_point)

Capabilities

Range Creation and Initialization

Create DateTimeRange instances from various input formats including datetime objects, ISO strings, and range text.

class DateTimeRange:
    def __init__(
        self,
        start_datetime: Union[datetime.datetime, str, None] = None,
        end_datetime: Union[datetime.datetime, str, None] = None,
        start_time_format: Optional[str] = None,
        end_time_format: Optional[str] = None,
        timezone: Optional[datetime.tzinfo] = None,
    ) -> None:
        """
        Initialize a DateTimeRange instance.
        
        Args:
            start_datetime: Start time as datetime object or ISO string
            end_datetime: End time as datetime object or ISO string  
            start_time_format: Custom format string for start time display
            end_time_format: Custom format string for end time display
            timezone: Timezone information for the range
        """

    @classmethod
    def from_range_text(
        cls,
        range_text: str,
        separator: str = r"\s+\-\s+",
        start_time_format: Optional[str] = None,
        end_time_format: Optional[str] = None,
        timezone: Optional[datetime.tzinfo] = None,
    ) -> "DateTimeRange":
        """
        Create DateTimeRange from text representation.
        
        Args:
            range_text: Text containing datetime range (e.g., "2021-01-23T10:00:00+0400 - 2021-01-23T10:10:00+0400")
            separator: Regex pattern separating start and end times
            start_time_format: Custom format for start time
            end_time_format: Custom format for end time
            timezone: Timezone information
            
        Returns:
            DateTimeRange: New instance from parsed text
        """

Properties and Attributes

Access datetime range properties and configure display formats.

@property
def start_datetime(self) -> Optional[datetime.datetime]:
    """Start time of the range."""

@property  
def end_datetime(self) -> Optional[datetime.datetime]:
    """End time of the range."""

@property
def timezone(self) -> Optional[datetime.tzinfo]:
    """Timezone information of the range."""

@property
def timedelta(self) -> datetime.timedelta:
    """Time difference between end and start as timedelta."""

# Instance attributes
start_time_format: str  # Format string for start time display (default: "%Y-%m-%dT%H:%M:%S%z")
end_time_format: str    # Format string for end time display (default: "%Y-%m-%dT%H:%M:%S%z")
is_output_elapse: bool  # Whether to show elapsed time in string representation
separator: str          # Separator string for display (default: " - ")

Time Range Management

Set and modify datetime range boundaries with validation.

def set_start_datetime(
    self, 
    value: Union[datetime.datetime, str, None], 
    timezone: Optional[datetime.tzinfo] = None
) -> None:
    """
    Set the start time of the range.
    
    Args:
        value: New start datetime or ISO string
        timezone: Timezone for the datetime
        
    Raises:
        ValueError: If value is invalid datetime
    """

def set_end_datetime(
    self, 
    value: Union[datetime.datetime, str, None], 
    timezone: Optional[datetime.tzinfo] = None
) -> None:
    """
    Set the end time of the range.
    
    Args:
        value: New end datetime or ISO string
        timezone: Timezone for the datetime
        
    Raises:
        ValueError: If value is invalid datetime
    """

def set_time_range(
    self,
    start: Union[datetime.datetime, str, None],
    end: Union[datetime.datetime, str, None],
    timezone: Optional[datetime.tzinfo] = None,
) -> None:
    """
    Set both start and end times.
    
    Args:
        start: Start datetime or ISO string
        end: End datetime or ISO string  
        timezone: Timezone for both times
    """

Validation and Queries

Validate time ranges and query their properties.

def is_set(self) -> bool:
    """
    Check if both start and end times are set.
    
    Returns:
        bool: True if both times are not None
    """

def is_time_inversion(self, allow_timezone_mismatch: bool = True) -> bool:
    """
    Check if start time is after end time.
    
    Args:
        allow_timezone_mismatch: Whether to ignore timezone differences
        
    Returns:
        bool: True if start > end
    """

def validate_time_inversion(self, allow_timezone_mismatch: bool = True) -> None:
    """
    Validate time order, raising exception if inverted.
    
    Args:
        allow_timezone_mismatch: Whether to ignore timezone differences
        
    Raises:
        ValueError: If start time > end time
        TypeError: If times are not set properly
    """

def is_valid_timerange(self) -> bool:
    """
    Check if range is valid (set and not inverted).
    
    Returns:
        bool: True if valid non-null, non-inverted range
    """

String Formatting

Convert datetime ranges to formatted string representations.

def get_start_time_str(self) -> str:
    """
    Get formatted start time string.
    
    Returns:
        str: Formatted start time or "NaT" if invalid
    """

def get_end_time_str(self) -> str:
    """
    Get formatted end time string.
    
    Returns:
        str: Formatted end time or "NaT" if invalid
    """

def get_timedelta_second(self) -> float:
    """
    Get time difference in seconds.
    
    Returns:
        float: Duration in seconds
    """

Range Operations

Perform set-like operations on datetime ranges including intersection, union, and subtraction.

def intersection(
    self,
    x: "DateTimeRange",
    intersection_threshold: Union[datetime.timedelta, relativedelta, None] = None,
) -> "DateTimeRange":
    """
    Create intersection of two time ranges.
    
    Args:
        x: Other DateTimeRange to intersect with
        intersection_threshold: Minimum overlap duration required
        
    Returns:
        DateTimeRange: Overlapping portion or empty range if no overlap
    """

def is_intersection(
    self,
    x: "DateTimeRange", 
    intersection_threshold: Union[datetime.timedelta, relativedelta, None] = None,
) -> bool:
    """
    Check if ranges intersect.
    
    Args:
        x: Other DateTimeRange to check
        intersection_threshold: Minimum overlap duration required
        
    Returns:
        bool: True if ranges overlap
    """

def subtract(self, x: "DateTimeRange") -> list["DateTimeRange"]:
    """
    Remove overlapping portion from this range.
    
    Args:
        x: DateTimeRange to subtract
        
    Returns:
        list[DateTimeRange]: List of remaining ranges after subtraction
    """

def encompass(self, x: "DateTimeRange") -> "DateTimeRange":
    """
    Create range that encompasses both ranges.
    
    Args:
        x: Other DateTimeRange to encompass
        
    Returns:
        DateTimeRange: Range spanning from earliest start to latest end
    """

Range Manipulation

Split, truncate, and modify datetime ranges.

def split(self, separator: Union[str, datetime.datetime]) -> list["DateTimeRange"]:
    """
    Split range at specific datetime.
    
    Args:
        separator: Datetime to split at (included in both resulting ranges)
        
    Returns:
        list[DateTimeRange]: List of split ranges (1 if separator outside range, 2 if inside)
    """

def truncate(self, percentage: float) -> None:
    """
    Remove percentage/2 from each end of the range.
    
    Args:
        percentage: Percentage to truncate (distributed equally from both ends)
        
    Raises:
        ValueError: If percentage < 0
    """

Range Iteration

Iterate through datetime ranges with custom step intervals.

def range(self, step: Union[datetime.timedelta, relativedelta]) -> Iterator[datetime.datetime]:
    """
    Iterate through range with specified step.
    
    Args:
        step: Time interval for iteration steps
        
    Returns:
        Iterator[datetime.datetime]: Iterator yielding datetime objects
        
    Raises:
        ValueError: If step is zero or invalid direction for inverted ranges
    """

Membership Testing

Test if datetimes or ranges are contained within this range.

def __contains__(self, x: Union[datetime.datetime, "DateTimeRange", str]) -> bool:
    """
    Check if datetime or range is within this range.
    
    Args:
        x: Datetime, DateTimeRange, or ISO string to test
        
    Returns:
        bool: True if x is contained within this range
    """

Arithmetic Operations

Add and subtract time intervals from datetime ranges.

def __add__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":
    """
    Add time interval to both start and end times.
    
    Args:
        other: Time interval to add
        
    Returns:
        DateTimeRange: New range shifted forward by interval
    """

def __iadd__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":
    """
    Add time interval in-place.
    
    Args:
        other: Time interval to add
        
    Returns:
        DateTimeRange: Self with modified times
    """

def __sub__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":
    """
    Subtract time interval from both start and end times.
    
    Args:
        other: Time interval to subtract
        
    Returns:
        DateTimeRange: New range shifted backward by interval
    """

def __isub__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":
    """
    Subtract time interval in-place.
    
    Args:
        other: Time interval to subtract
        
    Returns:
        DateTimeRange: Self with modified times
    """

String Representation and Comparison

Get string representation and compare datetime ranges.

def __repr__(self) -> str:
    """
    Get string representation of the datetime range.
    
    Returns:
        str: Formatted range with optional elapsed time if is_output_elapse is True
    """

def __eq__(self, other: object) -> bool:
    """
    Check equality with another DateTimeRange.
    
    Args:
        other: Object to compare with
        
    Returns:
        bool: True if both ranges have same start and end times
    """

def __ne__(self, other: object) -> bool:
    """
    Check inequality with another DateTimeRange.
    
    Args:
        other: Object to compare with
        
    Returns:
        bool: True if ranges differ in start or end times
    """

Constants

# Class constant for invalid time representation
NOT_A_TIME_STR: str = "NaT"

Types

from typing import Union, Optional, Iterator
import datetime
from dateutil.relativedelta import relativedelta

# Type aliases used throughout the API
TimeValue = Union[datetime.datetime, str, None]
TimeDelta = Union[datetime.timedelta, relativedelta]

Common Usage Patterns

Creating Ranges

# From ISO strings
range1 = DateTimeRange("2015-03-22T10:00:00+0900", "2015-03-22T10:10:00+0900")

# From datetime objects  
start = datetime.datetime(2015, 3, 22, 10, 0, 0)
end = datetime.datetime(2015, 3, 22, 10, 10, 0)
range2 = DateTimeRange(start, end)

# From range text
range3 = DateTimeRange.from_range_text("2015-03-22T10:00:00+0900 - 2015-03-22T10:10:00+0900")

Range Operations

# Intersection
overlap = range1.intersection(range2)

# Union (encompass)
combined = range1.encompass(range2)

# Subtraction
remaining = range1.subtract(range2)

# Membership testing
if "2015-03-22T10:05:00+0900" in range1:
    print("Time is in range")

Iteration and Stepping

# Daily iteration
for day in date_range.range(datetime.timedelta(days=1)):
    print(day)

# Hourly iteration using relativedelta
from dateutil.relativedelta import relativedelta
for hour in date_range.range(relativedelta(hours=1)):
    print(hour)

Timezone Handling

import pytz

# Create with timezone
tz = pytz.timezone('America/New_York')
range_tz = DateTimeRange(
    "2015-03-22T10:00:00",
    "2015-03-22T12:00:00", 
    timezone=tz
)