Skip to content

Temporal Expression APIs

All temporal operations are valid for both scalars and columns.

TemporalValue

Bases: Value

Source code in ibis/expr/types/temporal.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@public
class TemporalValue(Value):
    def strftime(self, format_str: str) -> ir.StringValue:
        """Format timestamp according to `format_str`.

        Format string may depend on the backend, but we try to conform to ANSI
        `strftime`.

        Parameters
        ----------
        format_str
            `strftime` format string

        Returns
        -------
        StringValue
            Formatted version of `arg`
        """
        return ops.Strftime(self, format_str).to_expr()

Functions

strftime(format_str)

Format timestamp according to format_str.

Format string may depend on the backend, but we try to conform to ANSI strftime.

Parameters:

Name Type Description Default
format_str str

strftime format string

required

Returns:

Type Description
StringValue

Formatted version of arg

Source code in ibis/expr/types/temporal.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def strftime(self, format_str: str) -> ir.StringValue:
    """Format timestamp according to `format_str`.

    Format string may depend on the backend, but we try to conform to ANSI
    `strftime`.

    Parameters
    ----------
    format_str
        `strftime` format string

    Returns
    -------
    StringValue
        Formatted version of `arg`
    """
    return ops.Strftime(self, format_str).to_expr()

TimestampValue

Bases: _DateComponentMixin, _TimeComponentMixin, TemporalValue

Source code in ibis/expr/types/temporal.py
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
@public
class TimestampValue(_DateComponentMixin, _TimeComponentMixin, TemporalValue):
    def truncate(
        self,
        unit: Literal["Y", "Q", "M", "W", "D", "h", "m", "s", "ms", "us", "ns"],
    ) -> TimestampValue:
        """Truncate timestamp expression to units of `unit`.

        Parameters
        ----------
        unit
            Unit to truncate to

        Returns
        -------
        TimestampValue
            Truncated timestamp expression
        """
        return ops.TimestampTruncate(self, unit).to_expr()

    def date(self) -> DateValue:
        """Return the date component of the expression.

        Returns
        -------
        DateValue
            The date component of `self`
        """
        return ops.Date(self).to_expr()

    def __add__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> TimestampValue | NotImplemented:
        """Add an interval to a timestamp."""
        return _binop(ops.TimestampAdd, self, other)

    add = radd = __radd__ = __add__
    """Add an interval to a timestamp.

    Parameters
    ----------
    other : datetime.timedelta | pd.Timedelta | IntervalValue
        Interval to subtract from timestamp

    Returns
    -------
    Value : TimestampValue | NotImplemented
    """

    def __sub__(
        self,
        other: datetime.datetime
        | pd.Timestamp
        | TimestampValue
        | datetime.timedelta
        | pd.Timedelta
        | IntervalValue,
    ) -> IntervalValue | TimestampValue | NotImplemented:
        """Subtract a timestamp or an interval from a timestamp."""
        import ibis.expr.rules as rlz

        right = rlz.any(other)

        if right.output_dtype.is_timestamp():
            op = ops.TimestampDiff
        else:
            op = ops.TimestampSub  # let the operation validate

        return _binop(op, self, other)

    sub = __sub__
    """Subtract a timestamp or an interval from a timestamp.

    Parameters
    ----------
    other : datetime.datetime | pd.Timestamp | TimestampValue | datetime.timedelta | pd.Timedelta | IntervalValue
        Timestamp or interval to subtract from timestamp

    Returns
    -------
    Value : IntervalValue | TimestampValue | NotImplemented
    """

    def __rsub__(
        self,
        other: datetime.datetime
        | pd.Timestamp
        | TimestampValue
        | datetime.timedelta
        | pd.Timedelta
        | IntervalValue,
    ) -> IntervalValue | TimestampValue | NotImplemented:
        """Subtract a timestamp or an interval from a timestamp."""
        import ibis.expr.rules as rlz

        right = rlz.any(other)

        if right.output_dtype.is_timestamp():
            op = ops.TimestampDiff
        else:
            op = ops.TimestampSub  # let the operation validate

        return _binop(op, other, self)

    rsub = __rsub__

Functions

add = __add__ class-attribute instance-attribute

Add an interval to a timestamp.

Parameters:

Name Type Description Default
other datetime.timedelta | pd.Timedelta | IntervalValue

Interval to subtract from timestamp

required

Returns:

Name Type Description
Value TimestampValue | NotImplemented

between(lower, upper, timezone=None)

Check if the expr falls between lower and upper, inclusive.

Adjusts according to timezone if provided.

Parameters:

Name Type Description Default
lower str | datetime.time | TimeValue

Lower bound

required
upper str | datetime.time | TimeValue

Upper bound

required
timezone str | None

Time zone

None

Returns:

Type Description
BooleanValue

Whether self is between lower and upper, adjusting timezone as needed.

date()

Return the date component of the expression.

Returns:

Type Description
DateValue

The date component of self

day()

Extract the day component.

day_of_week: DayOfWeek property

A namespace of methods for extracting day of week information.

Returns:

Type Description
DayOfWeek

An namespace expression containing methods to use to extract information.

day_of_year()

Extract the day of the year component.

epoch_seconds()

Extract UNIX epoch in seconds.

hour()

Extract the hour component.

millisecond()

Extract the millisecond component.

minute()

Extract the minute component.

month()

Extract the month component.

second()

Extract the second component.

strftime(format_str)

Format timestamp according to format_str.

Format string may depend on the backend, but we try to conform to ANSI strftime.

Parameters:

Name Type Description Default
format_str str

strftime format string

required

Returns:

Type Description
StringValue

Formatted version of arg

sub = __sub__ class-attribute instance-attribute

Subtract a timestamp or an interval from a timestamp.

Parameters:

Name Type Description Default
other datetime.datetime | pd.Timestamp | TimestampValue | datetime.timedelta | pd.Timedelta | IntervalValue

Timestamp or interval to subtract from timestamp

required

Returns:

Name Type Description
Value IntervalValue | TimestampValue | NotImplemented

time()

Return the time component of the expression.

Returns:

Type Description
TimeValue

The time component of self

truncate(unit)

Truncate timestamp expression to units of unit.

Parameters:

Name Type Description Default
unit Literal['Y', 'Q', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns']

Unit to truncate to

required

Returns:

Type Description
TimestampValue

Truncated timestamp expression

quarter()

Extract the quarter component.

week_of_year()

Extract the week of the year component.

year()

Extract the year component.

DateValue

Bases: TemporalValue, _DateComponentMixin

Source code in ibis/expr/types/temporal.py
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
@public
class DateValue(TemporalValue, _DateComponentMixin):
    def truncate(self, unit: Literal["Y", "Q", "M", "W", "D"]) -> DateValue:
        """Truncate date expression to units of `unit`.

        Parameters
        ----------
        unit
            Unit to truncate `arg` to

        Returns
        -------
        DateValue
            Truncated date value expression
        """
        return ops.DateTruncate(self, unit).to_expr()

    def __add__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> DateValue | NotImplemented:
        """Add an interval to a date."""
        return _binop(ops.DateAdd, self, other)

    add = radd = __radd__ = __add__
    """Add an interval to a date.

    Parameters
    ----------
    other : datetime.timedelta | pd.Timedelta | IntervalValue
        Interval to add to DateValue

    Returns
    -------
    Value : DateValue | NotImplemented
    """

    def __sub__(
        self,
        other: datetime.date
        | DateValue
        | datetime.timedelta
        | pd.Timedelta
        | IntervalValue,
    ) -> IntervalValue | DateValue | NotImplemented:
        """Subtract a date or an interval from a date."""
        import ibis.expr.rules as rlz

        other = rlz.one_of([rlz.date, rlz.interval], other)

        if other.output_dtype.is_date():
            op = ops.DateDiff
        else:
            op = ops.DateSub  # let the operation validate

        return _binop(op, self, other)

    sub = __sub__
    """Subtract a date or an interval from a date.

    Parameters
    ----------
    other : datetime.date | DateValue | datetime.timedelta | pd.Timedelta | IntervalValue
        Interval to subtract from DateValue

    Returns
    -------
    Value : DateValue | NotImplemented
    """

    def __rsub__(
        self,
        other: datetime.date
        | DateValue
        | datetime.timedelta
        | pd.Timedelta
        | IntervalValue,
    ) -> IntervalValue | DateValue | NotImplemented:
        """Subtract a date or an interval from a date."""
        import ibis.expr.rules as rlz

        other = rlz.one_of([rlz.date, rlz.interval], other)

        if other.output_dtype.is_date():
            op = ops.DateDiff
        else:
            op = ops.DateSub  # let the operation validate

        return _binop(op, other, self)

    rsub = __rsub__

Functions

add = __add__ class-attribute instance-attribute

Add an interval to a date.

Parameters:

Name Type Description Default
other datetime.timedelta | pd.Timedelta | IntervalValue

Interval to add to DateValue

required

Returns:

Name Type Description
Value DateValue | NotImplemented

day()

Extract the day component.

day_of_week: DayOfWeek property

A namespace of methods for extracting day of week information.

Returns:

Type Description
DayOfWeek

An namespace expression containing methods to use to extract information.

day_of_year()

Extract the day of the year component.

epoch_seconds()

Extract UNIX epoch in seconds.

month()

Extract the month component.

strftime(format_str)

Format timestamp according to format_str.

Format string may depend on the backend, but we try to conform to ANSI strftime.

Parameters:

Name Type Description Default
format_str str

strftime format string

required

Returns:

Type Description
StringValue

Formatted version of arg

sub = __sub__ class-attribute instance-attribute

Subtract a date or an interval from a date.

Parameters:

Name Type Description Default
other datetime.date | DateValue | datetime.timedelta | pd.Timedelta | IntervalValue

Interval to subtract from DateValue

required

Returns:

Name Type Description
Value DateValue | NotImplemented

truncate(unit)

Truncate date expression to units of unit.

Parameters:

Name Type Description Default
unit Literal['Y', 'Q', 'M', 'W', 'D']

Unit to truncate arg to

required

Returns:

Type Description
DateValue

Truncated date value expression

quarter()

Extract the quarter component.

week_of_year()

Extract the week of the year component.

year()

Extract the year component.

TimeValue

Bases: _TimeComponentMixin, TemporalValue

Source code in ibis/expr/types/temporal.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
@public
class TimeValue(_TimeComponentMixin, TemporalValue):
    def truncate(
        self,
        unit: Literal["h", "m", "s", "ms", "us", "ns"],
    ) -> TimeValue:
        """Truncate the expression to a time expression in units of `unit`.

        Commonly used for time series resampling.

        Parameters
        ----------
        unit
            The unit to truncate to

        Returns
        -------
        TimeValue
            `self` truncated to `unit`
        """
        return ops.TimeTruncate(self, unit).to_expr()

    def __add__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> TimeValue | NotImplemented:
        """Add an interval to a time expression."""
        return _binop(ops.TimeAdd, self, other)

    add = radd = __radd__ = __add__
    """Add an interval to a time expression.

    Parameters
    ----------
    other : datetime.timedelta | pd.Timedelta | IntervalValue
        Interval to add to time expression

    Returns
    -------
    Value : TimeValue | NotImplemented
    """

    def __sub__(
        self,
        other: TimeValue | IntervalValue,
    ) -> IntervalValue | TimeValue | NotImplemented:
        """Subtract a time or an interval from a time expression."""
        import ibis.expr.rules as rlz

        other = rlz.any(other)

        if other.output_dtype.is_time():
            op = ops.TimeDiff
        else:
            op = ops.TimeSub  # let the operation validate

        return _binop(op, self, other)

    sub = __sub__
    """Subtract a time or an interval from a time expression.

    Parameters
    ----------
    other : TimeValue | IntervalValue
        Interval to subtract from time expression

    Returns
    -------
    Value : IntervalValue | TimeValue | NotImplemented
    """

    def __rsub__(
        self,
        other: TimeValue | IntervalValue,
    ) -> IntervalValue | TimeValue | NotImplemented:
        """Subtract a time or an interval from a time expression."""
        import ibis.expr.rules as rlz

        other = rlz.any(other)

        if other.output_dtype.is_time():
            op = ops.TimeDiff
        else:
            op = ops.TimeSub  # let the operation validate

        return _binop(op, other, self)

    rsub = __rsub__

Functions

add = __add__ class-attribute instance-attribute

Add an interval to a time expression.

Parameters:

Name Type Description Default
other datetime.timedelta | pd.Timedelta | IntervalValue

Interval to add to time expression

required

Returns:

Name Type Description
Value TimeValue | NotImplemented

between(lower, upper, timezone=None)

Check if the expr falls between lower and upper, inclusive.

Adjusts according to timezone if provided.

Parameters:

Name Type Description Default
lower str | datetime.time | TimeValue

Lower bound

required
upper str | datetime.time | TimeValue

Upper bound

required
timezone str | None

Time zone

None

Returns:

Type Description
BooleanValue

Whether self is between lower and upper, adjusting timezone as needed.

hour()

Extract the hour component.

microsecond()

Extract the microsecond component.

millisecond()

Extract the millisecond component.

minute()

Extract the minute component.

second()

Extract the second component.

strftime(format_str)

Format timestamp according to format_str.

Format string may depend on the backend, but we try to conform to ANSI strftime.

Parameters:

Name Type Description Default
format_str str

strftime format string

required

Returns:

Type Description
StringValue

Formatted version of arg

sub = __sub__ class-attribute instance-attribute

Subtract a time or an interval from a time expression.

Parameters:

Name Type Description Default
other TimeValue | IntervalValue

Interval to subtract from time expression

required

Returns:

Name Type Description
Value IntervalValue | TimeValue | NotImplemented

time()

Return the time component of the expression.

Returns:

Type Description
TimeValue

The time component of self

truncate(unit)

Truncate the expression to a time expression in units of unit.

Commonly used for time series resampling.

Parameters:

Name Type Description Default
unit Literal['h', 'm', 's', 'ms', 'us', 'ns']

The unit to truncate to

required

Returns:

Type Description
TimeValue

self truncated to unit

IntervalValue

Bases: Value

Source code in ibis/expr/types/temporal.py
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
@public
class IntervalValue(Value):
    def to_unit(self, target_unit: str) -> IntervalValue:
        """Convert this interval to units of `target_unit`."""
        # TODO(kszucs): should use a separate operation for unit conversion
        # which we can rewrite/simplify to integer multiplication/division
        op = self.op()
        current_unit = op.output_dtype.unit
        target_unit = IntervalUnit.from_string(target_unit)

        if current_unit == target_unit:
            return self
        elif isinstance(op, ops.Literal):
            value = util.convert_unit(op.value, current_unit.short, target_unit.short)
            return ops.Literal(value, dtype=dt.Interval(target_unit)).to_expr()
        else:
            value = util.convert_unit(
                self.cast(dt.int64), current_unit.short, target_unit.short
            )
            return value.to_interval(target_unit)

    @property
    def years(self) -> ir.IntegerValue:
        """Extract the number of years from an interval."""
        return self.to_unit("Y")

    @property
    def quarters(self) -> ir.IntegerValue:
        """Extract the number of quarters from an interval."""
        return self.to_unit("Q")

    @property
    def months(self) -> ir.IntegerValue:
        """Extract the number of months from an interval."""
        return self.to_unit("M")

    @property
    def weeks(self) -> ir.IntegerValue:
        """Extract the number of weeks from an interval."""
        return self.to_unit("W")

    @property
    def days(self) -> ir.IntegerValue:
        """Extract the number of days from an interval."""
        return self.to_unit("D")

    @property
    def hours(self) -> ir.IntegerValue:
        """Extract the number of hours from an interval."""
        return self.to_unit("h")

    @property
    def minutes(self) -> ir.IntegerValue:
        """Extract the number of minutes from an interval."""
        return self.to_unit("m")

    @property
    def seconds(self) -> ir.IntegerValue:
        """Extract the number of seconds from an interval."""
        return self.to_unit("s")

    @property
    def milliseconds(self) -> ir.IntegerValue:
        """Extract the number of milliseconds from an interval."""
        return self.to_unit("ms")

    @property
    def microseconds(self) -> ir.IntegerValue:
        """Extract the number of microseconds from an interval."""
        return self.to_unit("us")

    @property
    def nanoseconds(self) -> ir.IntegerValue:
        """Extract the number of nanoseconds from an interval."""
        return self.to_unit("ns")

    def __add__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> IntervalValue | NotImplemented:
        """Add this interval to `other`."""
        return _binop(ops.IntervalAdd, self, other)

    add = radd = __radd__ = __add__

    def __sub__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> IntervalValue | NotImplemented:
        """Subtract `other` from this interval."""
        return _binop(ops.IntervalSubtract, self, other)

    sub = __sub__

    def __rsub__(
        self,
        other: datetime.timedelta | pd.Timedelta | IntervalValue,
    ) -> IntervalValue | NotImplemented:
        """Subtract `other` from this interval."""
        return _binop(ops.IntervalSubtract, other, self)

    rsub = __rsub__

    def __mul__(
        self,
        other: int | ir.IntegerValue,
    ) -> IntervalValue | NotImplemented:
        """Multiply this interval by `other`."""
        return _binop(ops.IntervalMultiply, self, other)

    mul = rmul = __rmul__ = __mul__

    def __floordiv__(
        self,
        other: ir.IntegerValue,
    ) -> IntervalValue | NotImplemented:
        """Floor-divide this interval by `other`."""
        return _binop(ops.IntervalFloorDivide, self, other)

    floordiv = __floordiv__

    def negate(self) -> ir.IntervalValue:
        """Negate an interval expression.

        Returns
        -------
        IntervalValue
            A negated interval value expression
        """
        op = self.op()
        if hasattr(op, "negate"):
            result = op.negate()
        else:
            result = ops.Negate(self)

        return result.to_expr()

    __neg__ = negate

    @staticmethod
    def __negate_op__():
        return ops.Negate

Attributes

days: ir.IntegerValue property

Extract the number of days from an interval.

hours: ir.IntegerValue property

Extract the number of hours from an interval.

microseconds: ir.IntegerValue property

Extract the number of microseconds from an interval.

milliseconds: ir.IntegerValue property

Extract the number of milliseconds from an interval.

minutes: ir.IntegerValue property

Extract the number of minutes from an interval.

months: ir.IntegerValue property

Extract the number of months from an interval.

nanoseconds: ir.IntegerValue property

Extract the number of nanoseconds from an interval.

quarters: ir.IntegerValue property

Extract the number of quarters from an interval.

seconds: ir.IntegerValue property

Extract the number of seconds from an interval.

weeks: ir.IntegerValue property

Extract the number of weeks from an interval.

years: ir.IntegerValue property

Extract the number of years from an interval.

Functions

negate()

Negate an interval expression.

Returns:

Type Description
IntervalValue

A negated interval value expression

Source code in ibis/expr/types/temporal.py
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
def negate(self) -> ir.IntervalValue:
    """Negate an interval expression.

    Returns
    -------
    IntervalValue
        A negated interval value expression
    """
    op = self.op()
    if hasattr(op, "negate"):
        result = op.negate()
    else:
        result = ops.Negate(self)

    return result.to_expr()

to_unit(target_unit)

Convert this interval to units of target_unit.

Source code in ibis/expr/types/temporal.py
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
def to_unit(self, target_unit: str) -> IntervalValue:
    """Convert this interval to units of `target_unit`."""
    # TODO(kszucs): should use a separate operation for unit conversion
    # which we can rewrite/simplify to integer multiplication/division
    op = self.op()
    current_unit = op.output_dtype.unit
    target_unit = IntervalUnit.from_string(target_unit)

    if current_unit == target_unit:
        return self
    elif isinstance(op, ops.Literal):
        value = util.convert_unit(op.value, current_unit.short, target_unit.short)
        return ops.Literal(value, dtype=dt.Interval(target_unit)).to_expr()
    else:
        value = util.convert_unit(
            self.cast(dt.int64), current_unit.short, target_unit.short
        )
        return value.to_interval(target_unit)

Last update: June 22, 2023