date_subtract()#

relationalai.std.dates
#date_subtract(
    date: date|datetime|Producer,
    period: Producer
) -> Expression

Subtracts a time period from a date or datetime value. Same as using the - operator with a period constructor. That is, date_subtract(date, period) is equivalent to date - period. If date or period is a Producer, then date_subtract() also acts as a filter and removes invalid values from the producer. In particular, if period is sub-day, then any date values produced by date are filtered out and the subtraction is only performed on datetime values. Must be called in a rule or query context.

IMPORTANT

date_subtract() cannot be used to subtract a date from another date. To subtract two dates or datetime value, use the - operator directly. See the date() and datetime() docs for more details.

Parameters#

NameTypeDescription
dateProducer or Python date or datetimeThe date or datetime value from which to subtract the period.
periodProducerThe time period to subtract from the date. May be one of:

Returns#

An Expression object. If date is a date value and period is one of years(), months(), or days(), then the Expression produces date values. If date is a datetime value, then the Expression produces datetime values.

Example#

You can use date_subtract() to subtract a time period from a date or datetime value. Typically, however, you use the - operator instead of calling date_subtract() directly:

#import relationalai as rai
from relationalai.std import alias, dates


# =====
# SETUP
# =====

model = rai.Model("MyModel")
Event = model.Type("Event")

with model.rule():
    Event.add(id=1).set(end=dates.datetime(2021, 1, 1, 9, 30), duration=dates.hours(1))
    Event.add(id=2).set(end=dates.date(2021, 2, 1), duration=dates.days(1))
    Event.add(id=3).set(end=dates.date(2021, 3, 1), duration=dates.hours(1))


# =======
# EXAMPLE
# =======

with model.rule():
    event = Event()
    # date_subtract() filters out any events with invalid start or duration values.
    # Event 3 has a date start value and a sub-day duration, so the following
    # only sets the start property for Events 1 and 2.
    event.set(start=event.end - event.duration)
    # Since Event 3 is filtered above, the following only sets the
    # has_valid_end_and_duration property for Events 1 and 2.
    event.set(has_valid_end_and_duration=True)

with model.query() as select:
    event = Event()
    response = select(event.id, event.start, event.has_valid_end_and_duration)

print(response.results)
#    id               start has_valid_end_and_duration
# 0   1 2021-01-01 08:30:00                       True
# 1   2 2021-01-31 00:00:00                       True
# 2   3                 NaT                        NaN

If you need to subtract a sub-day time period from a date, you can use datetime.fromdate() to convert the date to a datetime value before subtracting the period:

## Alternative version of the rule in the preceding example that converts any date
# values produced by event.end to datetime values before subtracting the duration.
with model.rule():
    event = Event()
    with model.match():
        # If event.start is a date, convert it to a datetime before subtracting the duration.
        with model.case():
            dates.Date(event.end)
            date_as_time = dates.datetime.fromdate(event.end)
            event.set(end=date_as_time - event.duration)
        # Otherwise, subtract the duration without conversion.
        with model.case():
            event.set(end=event.end - event.duration)

with model.query() as select:
    event = Event()
    response = select(event.id, event.start)

print(response.results)
#    id               start
# 0   1 2021-01-01 08:30:00
# 1   2 2021-01-31 00:00:00
# 2   3 2021-02-28 23:00:00

See Also#