time

time

Functions and classes for handling time

Hierarchy of TimePars: TimePar # All time parameters ├── dur # All durations, units of time │ ├── days # Duration with units of days │ ├── weeks │ ├── months │ ├── years │ └── datedur # Calendar durations └── Rate # All rates, units of per (e.g. per time or per event) ├── per # Probability rates over time (e.g., death rate per year) │ ├── perday │ ├── perweek │ ├── permonth │ └── peryear ├── prob # Unitless probability (e.g., probability of death per infection) │ ├── probperday │ ├── probperweek │ ├── probpermonth │ └── probperyear └── freq # Number of events (e.g., number of acts per year) ├── freqperday ├── freqperweek ├── freqpermonth └── freqperyear

Classes

Name Description
DateArray Lightweight wrapper for an array of dates
Rate Store a value per unit time e.g., 2 per day
TimePar Parent class for all TimePars – dur, Rate, etc.
date Define a point in time, based on pd.Timestamp
datedur Date based duration e.g., if requiring a week to be 7 calendar days later
dur Base class for durations
freq Class for the number of events (rather than probability) in a specified period
per A per represents an instantaneous rate of an event occurring. Rates
prob prob represents the probability of an event occurring during a

DateArray

time.DateArray()

Lightweight wrapper for an array of dates

Attributes

Name Description
subdaily Check if the array has sub-daily timesteps
years Represent the dates as floating point years

Methods

Name Description
is_ Checks if the DateArray is comprised of ss.date objects
to_array Force conversion to an array
to_date Convert to ss.date
to_float Convert to a float, returning a new DateArray unless inplace=True
to_human Return the most human-friendly (i.e. plotting-friendly) version of the dates,
is_
time.DateArray.is_(which)

Checks if the DateArray is comprised of ss.date objects

to_array
time.DateArray.to_array(*args, **kwargs)

Force conversion to an array

to_date
time.DateArray.to_date(inplace=False, day_round=None, die=True)

Convert to ss.date

Parameters
Name Type Description Default
inplace bool whether to modify in place False
round bool whether to round dates to the nearest day (otherwise, keep timestamp); if None, round if and only if the span of the first timestep is at least one day required
die bool if False, then fall back to float if conversion to date fails (e.g. year 0) True
to_float
time.DateArray.to_float(inplace=False, to_numpy=False)

Convert to a float, returning a new DateArray unless inplace=True

to_human
time.DateArray.to_human()

Return the most human-friendly (i.e. plotting-friendly) version of the dates, i.e. ss.date if possible, float otherwise

Rate

time.Rate(self, value, unit=None)

Store a value per unit time e.g., 2 per day - self.value - the numerator (e.g., 2) - a scalar float - self.unit - the denominator (e.g., 1 day) - a dur object

Methods

Name Description
set_default_dur Set the default duration, e.g. module.dt, so .to_prob() can be used with no input
to_events Simple multiplication: calculate the number of events over the time period
to_prob Convert from one time probability to another
set_default_dur
time.Rate.set_default_dur(dur)

Set the default duration, e.g. module.dt, so .to_prob() can be used with no input

to_events
time.Rate.to_events(dur=None)

Simple multiplication: calculate the number of events over the time period

to_prob
time.Rate.to_prob(dur=None, scale=1.0)

Convert from one time probability to another

Parameters
Name Type Description Default
dur ss.dur the duration over which to convert the probability to None
scale float an optional additional mutliplicative scale factor to incorporate in the calculation 1.0

Example:

p_month = ss.probpermonth(0.05)
p_year = p_month.to_prob(ss.year) # Slightly less than 0.05*12

TimePar

time.TimePar()

Parent class for all TimePars – dur, Rate, etc.

Methods

Name Description
to Convert this TimePar to one of a different class
to_array Force conversion to an array
to_base Class method to convert another TimePar object to this TimePar’s base units; in most cases
to
time.TimePar.to(unit)

Convert this TimePar to one of a different class

to_array
time.TimePar.to_array(*args, **kwargs)

Force conversion to an array

to_base
time.TimePar.to_base(other)

Class method to convert another TimePar object to this TimePar’s base units; in most cases

date

time.date()

Define a point in time, based on pd.Timestamp

Parameters

Name Type Description Default
date int / float / str / datetime Any type of date input (ints and floats will be interpreted as years) required
allow_zero bool if True, allow a year 0 by creating a datedur instead; if False, raise an exception; if None, give a warning required
kwargs dict passed to pd.Timestamp() required

Examples:

ss.date(2020) # Returns <2020-01-01>
ss.date(year=2020) # Returns <2020-01-01>
ss.date(year=2024.75) # Returns <2024-10-01>
ss.date('2024-04-04') # Returns <2024-04-04>
ss.date(year=2024, month=4, day=4) # Returns <2024-04-04>

Attributes

Name Description
years Return the date as a number of years

Methods

Name Description
arange Construct an array of dates
disp Show the full object
from_array Convert an array of float years into an array of date instances
from_json Reconstruct a date from a JSON; reverse of to_json()
from_year Convert an int or float year to a date.
replace Returns a new ss.date(); pd.Timestamp is immutable
round Round to a given interval (by default a day
subdaily Check if a subdaily timestep is used
to_json Returns a JSON representation of the date
to_pandas Convert to a standard pd.Timestamp instance
to_year Convert a date to a floating-point year
arange
time.date.arange(
    start,
    stop,
    step=1.0,
    inclusive=True,
    day_round=None,
    allow_zero=True,
)

Construct an array of dates

Functions similarly to np.arange, but returns date objects

Example usage:

date.arange(2020, 2025) array([<2020.01.01>, <2021.01.01>, <2022.01.01>, <2023.01.01>, <2024.01.01>, <2025.01.01>], dtype=object)

Parameters
Name Type Description Default
start float / ss.date / ss.dur Lower bound - can be a date or a numerical year required

stop (float/ss.date/ss.dur): Upper bound - can be a date or a numerical year step (float/ss.dur): Assumes 1 calendar year steps by default inclusive (bool): Whether to include “stop” in the output day_round (bool): Whether to round to the nearest day (by default, True if step > 1 day) allow_zero (bool): if True, allow a year 0 by creating a datedur instead; if False, raise an exception; if None, give a warning

Returns
Name Type Description
An array of date instances
disp
time.date.disp(**kwargs)

Show the full object

from_array
time.date.from_array(array, day_round=True, allow_zero=True, date_type=None)

Convert an array of float years into an array of date instances

Parameters
Name Type Description Default
array array An array of float years required
day_round bool Whether to round to the nearest day True
allow_zero bool if True, allow a year 0 by creating a datedur instead; if False, raise an exception; if None, give a warning True
date_type type Optionally convert to a class other than ss.date (e.g. ss.datedur) None
Returns
Name Type Description
An array of date instances
from_json
time.date.from_json(json)

Reconstruct a date from a JSON; reverse of to_json()

from_year
time.date.from_year(year, day_round=True, allow_zero=None)

Convert an int or float year to a date.

Parameters
Name Type Description Default
year float the year to round required
day_round bool whether to round to the nearest day True
allow_zero bool whether to allow year 0 (if so, return ss.datedur instead) None

Examples:

ss.date.from_year(2020) # Returns <2020-01-01>
ss.date.from_year(2024.75) # Returns <2024-10-01>
replace
time.date.replace(*args, **kwargs)

Returns a new ss.date(); pd.Timestamp is immutable

round
time.date.round(to='d')

Round to a given interval (by default a day

subdaily
time.date.subdaily(years)

Check if a subdaily timestep is used

A date has no concept of a timestep, but add this as a convienence method since this is required by other methods (e.g. ss.date.arange()).

to_json
time.date.to_json()

Returns a JSON representation of the date

to_pandas
time.date.to_pandas()

Convert to a standard pd.Timestamp instance

to_year
time.date.to_year()

Convert a date to a floating-point year

Examples:

ss.date('2020-01-01').to_year() # Returns 2020.0
ss.date('2024-10-01').to_year() # Returns 2024.7486

datedur

time.datedur(self, *args, **kwargs)

Date based duration e.g., if requiring a week to be 7 calendar days later

Attributes

Name Description
days Shortcut to datedur.to(‘days’)
months Shortcut to datedur.to(‘months’)
weeks Shortcut to datedur.to(‘weeks’)
years Shortcut to datedur.to(‘years’)

Methods

Name Description
round_duration Round a dictionary of duration values by overflowing remainders
scale Scale a pd.DateOffset by a factor
to Return approximate conversion into the provided quantity
to_array Convert to a Numpy array (NB, different than to_numpy() which converts to fractional years
to_dict Convert to a dictionary
to_dur Convert to the smallest non-zero value, e.g. ss.datedur(years=1, days=10).to_dur() = ss.days(375)
round_duration
time.datedur.round_duration(vals=None, **kwargs)

Round a dictionary of duration values by overflowing remainders

The input can be - A numpy array of length ss.time.factors containing values in key order - A pd.DateOffset instance - A dictionary with keys from ss.time.factors

The output will be a pd.DateOffset with integer values, where non-integer values have been handled by overflow using the factors in ss.time.factors. For example, 2.5 weeks would first become 2 weeks and 0.57 = 3.5 days, and then become 3 days + 0.524 = 12 hours.

Negative values are supported - -1.5 weeks for example will become (-1w, -3d, -12h)

Returns
Name Type Description
A pd.DateOffset
scale
time.datedur.scale(dateoffset, scale)

Scale a pd.DateOffset by a factor

This function will automatically cascade remainders to finer units using ss.time.factors so for example 2.5 weeks would first become 2 weeks and 0.57 = 3.5 days, and then become 3 days + 0.524 = 12 hours.

Parameters
Name Type Description Default
dateoffset A pd.DateOffset instance required
scale A float scaling factor (must be positive) required
Returns
Name Type Description
A pd.DateOffset instance scaled by the requested amount
to
time.datedur.to(unit)

Return approximate conversion into the provided quantity

This allows interoperability with years objects (which would typically be expected to occur if module parameters have been entered with datedur durations, but the simulation timestep is in years units).

The conversion is based on ss.time.factors which defines the conversion from each time unit to the next.

Parameters
Name Type Description Default
unit str the unit to convert to: years, months, weeks, or days required
Returns
Name Type Description
A float representing the duration in that unit
to_array
time.datedur.to_array(*args, **kwargs)

Convert to a Numpy array (NB, different than to_numpy() which converts to fractional years

to_dict
time.datedur.to_dict()

Convert to a dictionary

to_dur
time.datedur.to_dur()

Convert to the smallest non-zero value, e.g. ss.datedur(years=1, days=10).to_dur() = ss.days(375)

dur

time.dur(self, value=1, base=None)

Base class for durations

Note: this class should not be used by the user directly; instead, use ss.years(), ss.days(), etc. These classes can be interconverted using .to(), e.g. ss.years(3).to('days').

Methods

Name Description
arange Construct an array of dur instances
arange
time.dur.arange(start, stop, step=1.0, inclusive=True)

Construct an array of dur instances

Parameters
Name Type Description Default
start float / ss.dur Starting point, e.g., ss.years(0) required
stop float / ss.dur Ending point, e.g. ss.years(20) required
step float / ss.dur Step size, e.g. ss.years(2) 1.0

freq

time.freq(self, value, unit=None)

Class for the number of events (rather than probability) in a specified period

Identical to ss.per, except by default multiplication returns a number of events rather than a probability. Use ss.freq for events (e.g., number of acts per year) and ss.per for probabilities (e.g., probability of death per year).

Attributes

Name Description
rate Alias to self.value

per

time.per(self, value, unit=None)

A per represents an instantaneous rate of an event occurring. Rates must be non-negative, but need not be less than 1.

Through multiplication, rate can be modified or converted to a probability, depending on the data type of the object being multiplied.

When a per is multiplied by a scalar or array, the rate is simply scaled. Such multiplication occurs frequently in epidemiological models, where the base rate is multiplied by “rate ratio” or “relative rate” to represent agents experiencing higher (multiplier > 1) or lower (multiplier < 1) event rates.

Alternatively, when a per is multiplied by a duration (type ss.dur), a probability is calculated. The conversion from rate to probability on multiplication by a duration is 1 - np.exp(-rate/factor), where factor is the ratio of the multiplied duration to the original period (denominator).

For example, consider >>> p = ss.per(0.8, ss.years(1)) When multiplied by a duration of 1 year, the calculated probability is 1 - np.exp(-0.8), which is approximately 55%. >>> p*ss.years(1)

When multiplied by a scalar, the rate is simply scaled. >>> p*2

The difference between prob and per is subtle, but important. per works directly with the instantaneous rate of an event occurring. In contrast, prob starts with a probability and a duration, and the underlying rate is calculated. On multiplication by a duration, * per: rate -> probability * prob: probability -> rate -> probability

The behavior of both classes is depending on the data type of the object being multiplied.

ss.per is identical to ss.freq, except by default multiplication returns a probability rather than a number of events. Use ss.per for probabilities (e.g., probability of death per year), and ss.freq for events (e.g., number of acts per year).

Attributes

Name Description
rate Alias to self.value

prob

time.prob(self, value=None, unit=None, rate=None)

prob represents the probability of an event occurring during a specified period of time.

The class is designed to allow conversion of a probability from one duration to another through multiplication. However, the behavior of this conversion depends on the data type of the the object being multiplied.

When multiplied by a duration (type ss.dur), the underlying constant rate is calculated as rate = -np.log(1 - self.value). Then, the probability over the new duration is p = 1 - np.exp(-rate/factor), where factor is the ratio of the new duration to the original duration.

For example, >>> p = ss.prob(0.8, ss.years(1)) indicates a 80% chance of an event occurring in one year.

p*ss.years(1) When multiplied by the original denominator, 1 year in this case, the probability remains unchanged, 80%.

p * ss.years(2) Multiplying p by ss.years(2) does not simply double the probability to 160% (which is not possible), but rather returns a new probability of 96% representing the chance of the event occurring at least once over the new duration of two years.

However, the behavior is different when a prob object is multiplied by a scalar or array. In this case, the probability is simply scaled. This scaling may result in a value greater than 1, which is not valid. For example, >>> p * 2 raises an AssertionError because the resulting probability (160%) exceeds 100%.

Use per instead if prob if you would prefer to directly specify the instantaneous rate.

Methods

Name Description
to_prob Convert from one time probability to another
to_prob
time.prob.to_prob(dur=None, scale=1.0)

Convert from one time probability to another

Parameters
Name Type Description Default
dur ss.dur the duration over which to convert the probability to None
scale float an optional additional mutliplicative scale factor to incorporate in the calculation 1.0

Example:

p_month = ss.probpermonth(0.05)
p_year = p_month.to_prob(ss.year) # Slightly less than 0.05*12

Functions

Name Description
rate Backwards compatibility function for Rate
rate_prob Backwards compatibility function for per
time_prob Backwards compatibility function for prob

rate

time.rate(value, unit=None)

Backwards compatibility function for Rate

rate_prob

time.rate_prob(value, unit=None)

Backwards compatibility function for per

time_prob

time.time_prob(value, unit=None)

Backwards compatibility function for prob