or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

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

0

# DateTimeRange

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: DateTimeRange

7

- **Language**: Python

8

- **Installation**: `pip install DateTimeRange`

9

- **Requirements**: Python 3.9+

10

11

## Core Imports

12

13

```python

14

from datetimerange import DateTimeRange

15

```

16

17

## Basic Usage

18

19

```python

20

import datetime

21

from datetimerange import DateTimeRange

22

23

# Create a time range from string representations

24

time_range = DateTimeRange("2015-03-22T10:00:00+0900", "2015-03-22T10:10:00+0900")

25

print(time_range) # 2015-03-22T10:00:00+0900 - 2015-03-22T10:10:00+0900

26

27

# Create from datetime objects

28

start = datetime.datetime(2015, 3, 22, 10, 0, 0)

29

end = datetime.datetime(2015, 3, 22, 10, 10, 0)

30

time_range = DateTimeRange(start, end)

31

32

# Check if a time is within the range

33

check_time = "2015-03-22T10:05:00+0900"

34

print(check_time in time_range) # True

35

36

# Get intersection of two ranges

37

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

38

range2 = DateTimeRange("2015-03-22T10:05:00+0900", "2015-03-22T10:15:00+0900")

39

intersection = range1.intersection(range2)

40

print(intersection) # 2015-03-22T10:05:00+0900 - 2015-03-22T10:10:00+0900

41

42

# Iterate through time range with step intervals

43

import datetime

44

for time_point in time_range.range(datetime.timedelta(minutes=2)):

45

print(time_point)

46

```

47

48

## Capabilities

49

50

### Range Creation and Initialization

51

52

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

53

54

```python { .api }

55

class DateTimeRange:

56

def __init__(

57

self,

58

start_datetime: Union[datetime.datetime, str, None] = None,

59

end_datetime: Union[datetime.datetime, str, None] = None,

60

start_time_format: Optional[str] = None,

61

end_time_format: Optional[str] = None,

62

timezone: Optional[datetime.tzinfo] = None,

63

) -> None:

64

"""

65

Initialize a DateTimeRange instance.

66

67

Args:

68

start_datetime: Start time as datetime object or ISO string

69

end_datetime: End time as datetime object or ISO string

70

start_time_format: Custom format string for start time display

71

end_time_format: Custom format string for end time display

72

timezone: Timezone information for the range

73

"""

74

75

@classmethod

76

def from_range_text(

77

cls,

78

range_text: str,

79

separator: str = r"\s+\-\s+",

80

start_time_format: Optional[str] = None,

81

end_time_format: Optional[str] = None,

82

timezone: Optional[datetime.tzinfo] = None,

83

) -> "DateTimeRange":

84

"""

85

Create DateTimeRange from text representation.

86

87

Args:

88

range_text: Text containing datetime range (e.g., "2021-01-23T10:00:00+0400 - 2021-01-23T10:10:00+0400")

89

separator: Regex pattern separating start and end times

90

start_time_format: Custom format for start time

91

end_time_format: Custom format for end time

92

timezone: Timezone information

93

94

Returns:

95

DateTimeRange: New instance from parsed text

96

"""

97

```

98

99

### Properties and Attributes

100

101

Access datetime range properties and configure display formats.

102

103

```python { .api }

104

@property

105

def start_datetime(self) -> Optional[datetime.datetime]:

106

"""Start time of the range."""

107

108

@property

109

def end_datetime(self) -> Optional[datetime.datetime]:

110

"""End time of the range."""

111

112

@property

113

def timezone(self) -> Optional[datetime.tzinfo]:

114

"""Timezone information of the range."""

115

116

@property

117

def timedelta(self) -> datetime.timedelta:

118

"""Time difference between end and start as timedelta."""

119

120

# Instance attributes

121

start_time_format: str # Format string for start time display (default: "%Y-%m-%dT%H:%M:%S%z")

122

end_time_format: str # Format string for end time display (default: "%Y-%m-%dT%H:%M:%S%z")

123

is_output_elapse: bool # Whether to show elapsed time in string representation

124

separator: str # Separator string for display (default: " - ")

125

```

126

127

### Time Range Management

128

129

Set and modify datetime range boundaries with validation.

130

131

```python { .api }

132

def set_start_datetime(

133

self,

134

value: Union[datetime.datetime, str, None],

135

timezone: Optional[datetime.tzinfo] = None

136

) -> None:

137

"""

138

Set the start time of the range.

139

140

Args:

141

value: New start datetime or ISO string

142

timezone: Timezone for the datetime

143

144

Raises:

145

ValueError: If value is invalid datetime

146

"""

147

148

def set_end_datetime(

149

self,

150

value: Union[datetime.datetime, str, None],

151

timezone: Optional[datetime.tzinfo] = None

152

) -> None:

153

"""

154

Set the end time of the range.

155

156

Args:

157

value: New end datetime or ISO string

158

timezone: Timezone for the datetime

159

160

Raises:

161

ValueError: If value is invalid datetime

162

"""

163

164

def set_time_range(

165

self,

166

start: Union[datetime.datetime, str, None],

167

end: Union[datetime.datetime, str, None],

168

timezone: Optional[datetime.tzinfo] = None,

169

) -> None:

170

"""

171

Set both start and end times.

172

173

Args:

174

start: Start datetime or ISO string

175

end: End datetime or ISO string

176

timezone: Timezone for both times

177

"""

178

```

179

180

### Validation and Queries

181

182

Validate time ranges and query their properties.

183

184

```python { .api }

185

def is_set(self) -> bool:

186

"""

187

Check if both start and end times are set.

188

189

Returns:

190

bool: True if both times are not None

191

"""

192

193

def is_time_inversion(self, allow_timezone_mismatch: bool = True) -> bool:

194

"""

195

Check if start time is after end time.

196

197

Args:

198

allow_timezone_mismatch: Whether to ignore timezone differences

199

200

Returns:

201

bool: True if start > end

202

"""

203

204

def validate_time_inversion(self, allow_timezone_mismatch: bool = True) -> None:

205

"""

206

Validate time order, raising exception if inverted.

207

208

Args:

209

allow_timezone_mismatch: Whether to ignore timezone differences

210

211

Raises:

212

ValueError: If start time > end time

213

TypeError: If times are not set properly

214

"""

215

216

def is_valid_timerange(self) -> bool:

217

"""

218

Check if range is valid (set and not inverted).

219

220

Returns:

221

bool: True if valid non-null, non-inverted range

222

"""

223

```

224

225

### String Formatting

226

227

Convert datetime ranges to formatted string representations.

228

229

```python { .api }

230

def get_start_time_str(self) -> str:

231

"""

232

Get formatted start time string.

233

234

Returns:

235

str: Formatted start time or "NaT" if invalid

236

"""

237

238

def get_end_time_str(self) -> str:

239

"""

240

Get formatted end time string.

241

242

Returns:

243

str: Formatted end time or "NaT" if invalid

244

"""

245

246

def get_timedelta_second(self) -> float:

247

"""

248

Get time difference in seconds.

249

250

Returns:

251

float: Duration in seconds

252

"""

253

```

254

255

### Range Operations

256

257

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

258

259

```python { .api }

260

def intersection(

261

self,

262

x: "DateTimeRange",

263

intersection_threshold: Union[datetime.timedelta, relativedelta, None] = None,

264

) -> "DateTimeRange":

265

"""

266

Create intersection of two time ranges.

267

268

Args:

269

x: Other DateTimeRange to intersect with

270

intersection_threshold: Minimum overlap duration required

271

272

Returns:

273

DateTimeRange: Overlapping portion or empty range if no overlap

274

"""

275

276

def is_intersection(

277

self,

278

x: "DateTimeRange",

279

intersection_threshold: Union[datetime.timedelta, relativedelta, None] = None,

280

) -> bool:

281

"""

282

Check if ranges intersect.

283

284

Args:

285

x: Other DateTimeRange to check

286

intersection_threshold: Minimum overlap duration required

287

288

Returns:

289

bool: True if ranges overlap

290

"""

291

292

def subtract(self, x: "DateTimeRange") -> list["DateTimeRange"]:

293

"""

294

Remove overlapping portion from this range.

295

296

Args:

297

x: DateTimeRange to subtract

298

299

Returns:

300

list[DateTimeRange]: List of remaining ranges after subtraction

301

"""

302

303

def encompass(self, x: "DateTimeRange") -> "DateTimeRange":

304

"""

305

Create range that encompasses both ranges.

306

307

Args:

308

x: Other DateTimeRange to encompass

309

310

Returns:

311

DateTimeRange: Range spanning from earliest start to latest end

312

"""

313

```

314

315

### Range Manipulation

316

317

Split, truncate, and modify datetime ranges.

318

319

```python { .api }

320

def split(self, separator: Union[str, datetime.datetime]) -> list["DateTimeRange"]:

321

"""

322

Split range at specific datetime.

323

324

Args:

325

separator: Datetime to split at (included in both resulting ranges)

326

327

Returns:

328

list[DateTimeRange]: List of split ranges (1 if separator outside range, 2 if inside)

329

"""

330

331

def truncate(self, percentage: float) -> None:

332

"""

333

Remove percentage/2 from each end of the range.

334

335

Args:

336

percentage: Percentage to truncate (distributed equally from both ends)

337

338

Raises:

339

ValueError: If percentage < 0

340

"""

341

```

342

343

### Range Iteration

344

345

Iterate through datetime ranges with custom step intervals.

346

347

```python { .api }

348

def range(self, step: Union[datetime.timedelta, relativedelta]) -> Iterator[datetime.datetime]:

349

"""

350

Iterate through range with specified step.

351

352

Args:

353

step: Time interval for iteration steps

354

355

Returns:

356

Iterator[datetime.datetime]: Iterator yielding datetime objects

357

358

Raises:

359

ValueError: If step is zero or invalid direction for inverted ranges

360

"""

361

```

362

363

### Membership Testing

364

365

Test if datetimes or ranges are contained within this range.

366

367

```python { .api }

368

def __contains__(self, x: Union[datetime.datetime, "DateTimeRange", str]) -> bool:

369

"""

370

Check if datetime or range is within this range.

371

372

Args:

373

x: Datetime, DateTimeRange, or ISO string to test

374

375

Returns:

376

bool: True if x is contained within this range

377

"""

378

```

379

380

### Arithmetic Operations

381

382

Add and subtract time intervals from datetime ranges.

383

384

```python { .api }

385

def __add__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":

386

"""

387

Add time interval to both start and end times.

388

389

Args:

390

other: Time interval to add

391

392

Returns:

393

DateTimeRange: New range shifted forward by interval

394

"""

395

396

def __iadd__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":

397

"""

398

Add time interval in-place.

399

400

Args:

401

other: Time interval to add

402

403

Returns:

404

DateTimeRange: Self with modified times

405

"""

406

407

def __sub__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":

408

"""

409

Subtract time interval from both start and end times.

410

411

Args:

412

other: Time interval to subtract

413

414

Returns:

415

DateTimeRange: New range shifted backward by interval

416

"""

417

418

def __isub__(self, other: Union[datetime.timedelta, relativedelta]) -> "DateTimeRange":

419

"""

420

Subtract time interval in-place.

421

422

Args:

423

other: Time interval to subtract

424

425

Returns:

426

DateTimeRange: Self with modified times

427

"""

428

```

429

430

### String Representation and Comparison

431

432

Get string representation and compare datetime ranges.

433

434

```python { .api }

435

def __repr__(self) -> str:

436

"""

437

Get string representation of the datetime range.

438

439

Returns:

440

str: Formatted range with optional elapsed time if is_output_elapse is True

441

"""

442

443

def __eq__(self, other: object) -> bool:

444

"""

445

Check equality with another DateTimeRange.

446

447

Args:

448

other: Object to compare with

449

450

Returns:

451

bool: True if both ranges have same start and end times

452

"""

453

454

def __ne__(self, other: object) -> bool:

455

"""

456

Check inequality with another DateTimeRange.

457

458

Args:

459

other: Object to compare with

460

461

Returns:

462

bool: True if ranges differ in start or end times

463

"""

464

```

465

466

## Constants

467

468

```python { .api }

469

# Class constant for invalid time representation

470

NOT_A_TIME_STR: str = "NaT"

471

```

472

473

## Types

474

475

```python { .api }

476

from typing import Union, Optional, Iterator

477

import datetime

478

from dateutil.relativedelta import relativedelta

479

480

# Type aliases used throughout the API

481

TimeValue = Union[datetime.datetime, str, None]

482

TimeDelta = Union[datetime.timedelta, relativedelta]

483

```

484

485

## Common Usage Patterns

486

487

### Creating Ranges

488

489

```python

490

# From ISO strings

491

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

492

493

# From datetime objects

494

start = datetime.datetime(2015, 3, 22, 10, 0, 0)

495

end = datetime.datetime(2015, 3, 22, 10, 10, 0)

496

range2 = DateTimeRange(start, end)

497

498

# From range text

499

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

500

```

501

502

### Range Operations

503

504

```python

505

# Intersection

506

overlap = range1.intersection(range2)

507

508

# Union (encompass)

509

combined = range1.encompass(range2)

510

511

# Subtraction

512

remaining = range1.subtract(range2)

513

514

# Membership testing

515

if "2015-03-22T10:05:00+0900" in range1:

516

print("Time is in range")

517

```

518

519

### Iteration and Stepping

520

521

```python

522

# Daily iteration

523

for day in date_range.range(datetime.timedelta(days=1)):

524

print(day)

525

526

# Hourly iteration using relativedelta

527

from dateutil.relativedelta import relativedelta

528

for hour in date_range.range(relativedelta(hours=1)):

529

print(hour)

530

```

531

532

### Timezone Handling

533

534

```python

535

import pytz

536

537

# Create with timezone

538

tz = pytz.timezone('America/New_York')

539

range_tz = DateTimeRange(

540

"2015-03-22T10:00:00",

541

"2015-03-22T12:00:00",

542

timezone=tz

543

)

544

```