sciris.sc_datetime

Time/date utilities.

Highlights:
  • sc.tic()/sc.toc()/sc.timer(): simple methods for timing durations

  • sc.readdate(): convert strings to dates using common formats

  • sc.daterange(): create a list of dates

  • sc.datedelta(): perform calculations on date strings

Functions

date

Convert any reasonable object -- a string, integer, or datetime object, or list/array of any of those -- to a date object.

datedelta

Perform calculations on a date string (or date object), returning a string (or a date).

daterange

Return a list of dates from the start date to the end date.

datetoyear

Convert a DateTime instance to decimal year.

day

Convert a string, date/datetime object, or int to a day (int), the number of days since the start day.

daydiff

Convenience function to find the difference between two or more days.

elapsedtimestr

Accepts a datetime object or a string in ISO 8601 format and returns a human-readable string explaining when this time was.

getdate

Alias for converting a date object to a formatted string.

now

Get the current time as a datetime object, optionally in UTC time.

readdate

Convenience function for loading a date from a string.

tic

With sc.toc(), a little pair of functions to calculate a time difference:

timedsleep

Delay for a certain amount of time, to ensure accurate timing.

toc

With sc.tic(), a little pair of functions to calculate a time difference.

toctic

A convenience fu`ction for multiple timings.

Classes

Timer

alias of sciris.sc_datetime.timer

timer

Simple timer class.

now(astype='dateobj', timezone=None, utc=False, dateformat=None)[source]

Get the current time as a datetime object, optionally in UTC time.

sc.now() is similar to sc.getdate(), but sc.now() returns a datetime object by default, while sc.getdate() returns a string by default.

Parameters
  • astype (str) – what to return; choices are “dateobj”, “str”, “float”; see sc.getdate() for more

  • timezone (str) – the timezone to set the itme to

  • utc (bool) – whether the time is specified in UTC time

  • dateformat (str) – if astype is 'str', use this output format

Examples:

sc.now() # Return current local time, e.g. 2019-03-14 15:09:26
sc.now(timezone='US/Pacific') # Return the time now in a specific timezone
sc.now(utc=True) # Return the time in UTC
sc.now(astype='str') # Return the current time as a string instead of a date object; use 'int' for seconds
sc.now(tostring=True) # Backwards-compatible alias for astype='str'
sc.now(dateformat='%Y-%b-%d') # Return a different date format

New in version 1.3.0: made “astype” the first argument; removed “tostring” argument

getdate(obj=None, astype='str', dateformat=None)[source]

Alias for converting a date object to a formatted string.

See also sc.now().

Parameters
  • obj (datetime) – the datetime object to convert

  • astype (str) – what to return; choices are “str” (default), “dateobj”, “float” (full timestamp), “int” (timestamp to second precision)

  • dateformat (str) – if astype is 'str', use this output format

Examples:

sc.getdate() # Returns a string for the current date
sc.getdate(astype='float') # Convert today's time to a timestamp
readdate(datestr=None, *args, dateformat=None, return_defaults=False)[source]

Convenience function for loading a date from a string. If dateformat is None, this function tries a list of standard date types.

By default, a numeric date is treated as a POSIX (Unix) timestamp. This can be changed with the dateformat argument, specifically:

  • ‘posix’/None: treat as a POSIX timestamp, in seconds from 1970

  • ‘ordinal’/’matplotlib’: treat as an ordinal number of days from 1970 (Matplotlib default)

Parameters
  • datestr (int, float, str or list) – the string containing the date, or the timestamp (in seconds), or a list of either

  • args (list) – additional dates to convert

  • dateformat (str or list) – the format for the date, if known; if ‘dmy’ or ‘mdy’, try as day-month-year or month-day-year formats; can also be a list of options

  • return_defaults (bool) – don’t convert the date, just return the defaults

Returns

a datetime object

Return type

dateobj (date)

Examples:

dateobj  = sc.readdate('2020-03-03') # Standard format, so works
dateobj  = sc.readdate('04-03-2020', dateformat='dmy') # Date is ambiguous, so need to specify day-month-year order
dateobj  = sc.readdate(1611661666) # Can read timestamps as well
dateobj  = sc.readdate(16166, dateformat='ordinal') # Or ordinal numbers of days, as used by Matplotlib
dateobjs = sc.readdate(['2020-06', '2020-07'], dateformat='%Y-%m') # Can read custom date formats
dateobjs = sc.readdate('20200321', 1611661666) # Can mix and match formats
date(obj, *args, start_date=None, readformat=None, outformat=None, as_date=True, **kwargs)[source]

Convert any reasonable object – a string, integer, or datetime object, or list/array of any of those – to a date object. To convert an integer to a date, you must supply a start date.

Caution: while this function and sc.readdate() are similar, and indeed this function calls sc.readdate() if the input is a string, in this function an integer is treated as a number of days from start_date, while for sc.readdate() it is treated as a timestamp in seconds.

Note: in this and other date functions, arguments work either with or without underscores (e.g. start_date or startdate)

Parameters
  • obj (str/int/date/datetime/list/array) – the object to convert

  • args (str/int/date/datetime) – additional objects to convert

  • start_date (str/date/datetime) – the starting date, if an integer is supplied

  • readformat (str/list) – the format to read the date in; passed to sc.readdate()

  • outformat (str) – the format to output the date in, if returning a string

  • as_date (bool) – whether to return as a datetime date instead of a string

Returns

either a single date object, or a list of them (matching input data type where possible)

Return type

dates (date or list)

Examples:

sc.date('2020-04-05') # Returns datetime.date(2020, 4, 5)
sc.date([35,36,37], start_date='2020-01-01', as_date=False) # Returns ['2020-02-05', '2020-02-06', '2020-02-07']
sc.date(1923288822, readformat='posix') # Interpret as a POSIX timestamp
New in version 1.0.0.
New in version 1.2.2: “readformat” argument; renamed “dateformat” to “outformat”
day(obj, *args, start_date=None, **kwargs)[source]

Convert a string, date/datetime object, or int to a day (int), the number of days since the start day. See also sc.date() and sc.daydiff(). If a start day is not supplied, it returns the number of days into the current year.

Parameters
  • obj (str, date, int, list, array) – convert any of these objects to a day relative to the start day

  • args (list) – additional days

  • start_date (str or date) – the start day; if none is supplied, return days since (supplied year)-01-01.

Returns

the day(s) in simulation time (matching input data type where possible)

Return type

days (int or list)

Examples:

sc.day(sc.now()) # Returns how many days into the year we are
sc.day(['2021-01-21', '2024-04-04'], start_date='2022-02-22') # Days can be positive or negative
New in version 1.0.0.
New in version 1.2.2: renamed “start_day” to “start_date”
daydiff(*args)[source]

Convenience function to find the difference between two or more days. With only one argument, calculate days since 2020-01-01.

Examples:

diff  = sc.daydiff('2020-03-20', '2020-04-05') # Returns 16
diffs = sc.daydiff('2020-03-20', '2020-04-05', '2020-05-01') # Returns [16, 26]

New in version 1.0.0.

daterange(start_date=None, end_date=None, interval=None, inclusive=True, as_date=False, readformat=None, outformat=None, **kwargs)[source]

Return a list of dates from the start date to the end date. To convert a list of days (as integers) to dates, use sc.date() instead.

Parameters
  • start_date (int/str/date) – the starting date, in any format

  • end_date (int/str/date) – the end date, in any format

  • interval (int/str/dict) – if an int, the number of days; if ‘week’, ‘month’, or ‘year’, one of those; if a dict, passed to dt.relativedelta()

  • inclusive (bool) – if True (default), return to end_date inclusive; otherwise, stop the day before

  • as_date (bool) – if True, return a list of datetime.date objects instead of strings (note: you can also use “asdate” instead of “as_date”)

  • readformat (str) – passed to date()

  • outformat (str) – passed to date()

Examples:

dates1 = sc.daterange('2020-03-01', '2020-04-04')
dates2 = sc.daterange('2020-03-01', '2022-05-01', interval=dict(months=2), asdate=True)
New in version 1.0.0.
New in version 1.3.0: “interval” argument
datedelta(datestr=None, days=0, months=0, years=0, weeks=0, dt1=None, dt2=None, as_date=None, **kwargs)[source]

Perform calculations on a date string (or date object), returning a string (or a date). Wrapper to dateutil.relativedelta.relativedelta().

If datestr is None, then return the delta object rather than the new date.

Parameters
  • datestr (None/str/date) – the starting date (typically a string); if None, return the relative delta

  • days (int) – the number of days (positive or negative) to increment

  • months (int) – as above

  • years (int) – as above

  • weeks (int) – as above

  • dt1 (dates) – if both provided, compute the difference between them

  • dt2 (dates) – if both provided, compute the difference between them

  • as_date (bool) – if True, return a date object; otherwise, return as input type

  • kwargs (dict) – passed to sc.readdate()

Examples:

sc.datedelta('2021-07-07', 3) # Add 3 days
sc.datedelta('2021-07-07', days=-4) # Subtract 4 days
sc.datedelta('2021-07-07', weeks=4, months=-1, as_date=True) # Add 4 weeks but subtract a month, and return a dateobj
sc.datedelta(days=3) # Alias to du.relativedelta.relativedelta(days=3)
datetoyear(dateobj, dateformat=None)[source]

Convert a DateTime instance to decimal year.

Parameters
  • dateobj (date, str) – The datetime instance to convert

  • dateformat (str) – If dateobj is a string, the optional date conversion format to use

Returns

Equivalent decimal year

Example:

sc.datetoyear('2010-07-01') # Returns approximately 2010.5

By Luke Davis from https://stackoverflow.com/a/42424261, adapted by Romesh Abeysuriya.

New in version 1.0.0.

tic()[source]

With sc.toc(), a little pair of functions to calculate a time difference:

Examples:

sc.tic()
slow_func()
sc.toc()

T = sc.tic()
slow_func2()
sc.toc(T, label='slow_func2')

See also sc.timer().

toc(start=None, label=None, baselabel=None, sigfigs=None, reset=False, output=False, doprint=None, elapsed=None)[source]

With sc.tic(), a little pair of functions to calculate a time difference. See also sc.timer().

Parameters
  • start (float) – the starting time, as returned by e.g. sc.tic()

  • label (str) – optional label to add

  • baselabel (str) – optional base label; default is “Elapsed time: “

  • sigfigs (int) – number of significant figures for time estimate

  • reset (bool) – reset the time; like calling sc.toctic() or sc.tic() again

  • output (bool) – whether to return the output (otherwise print); if output=’message’, then return the message string; if output=’both’, then return both

  • doprint (bool) – whether to print (true by default)

  • elapsed (float) – use a pre-calculated elapsed time instead of recalculating (not recommneded)

Examples:

sc.tic()
slow_func()
sc.toc()

T = sc.tic()
slow_func2()
sc.toc(T, label='slow_func2')

New in version 1.3.0: new arguments.

toctic(returntic=False, returntoc=False, *args, **kwargs)[source]

A convenience fu`ction for multiple timings. Can return the default output of either sc.tic() or sc.toc() (default neither). Arguments are passed to sc.toc(). Equivalent to sc.toc(reset=True).

Example:

sc.tic()
slow_operation_1()
sc.toctic()
slow_operation_2()
sc.toc()

New in version 1.0.0.

class timer(label=None, auto=False, **kwargs)[source]

Simple timer class. Note: sc.timer() and sc.Timer() are aliases.

This wraps tic and toc with the formatting arguments and the start time (at construction).

Use this in a with block to automatically print elapsed time when the block finishes.

Parameters
  • label (str) – label identifying this timer

  • auto (bool) – whether to automatically increment the label

Example making repeated calls to the same timer, using auto to keep track:

>>> T = sc.timer(auto=True)
>>> T.toc()
Elapsed time for (0): 2.63 s
>>> T.toc()
Elapsed time for (1): 5.00 s

Example wrapping code using with-as:

>>> with sc.timer('mylabel'):
>>>     sc.timedsleep(0.5)

Example using a timer to collect data, using tt() as an alias for toctic() to reset the time:

T = sc.timer(doprint=False)
for key in 'abcde':
    sc.timedsleep(pl.rand())
    T.tt(key)
print(T.timings)

Implementation based on https://preshing.com/20110924/timing-your-code-using-pythons-with-statement/

New in version 1.3.0: sc.timer() alias, and allowing the label as first argument.
New in version 1.3.2: toc() passes label correctly; tt() method; auto argument
tic()[source]

Set start time

toc(label=None, **kwargs)[source]

Print elapsed time; see sc.toc() for keyword arguments

start()[source]

Alias for tic()

stop(*args, **kwargs)[source]

Alias for toc()

toctic(*args, **kwargs)[source]

Reset time between timings

tt(*args, **kwargs)[source]

Alias for toctic()

Timer

alias of sciris.sc_datetime.timer

elapsedtimestr(pasttime, maxdays=5, minseconds=10, shortmonths=True)[source]

Accepts a datetime object or a string in ISO 8601 format and returns a human-readable string explaining when this time was.

The rules are as follows:

  • If a time is within the last hour, return ‘XX minutes’

  • If a time is within the last 24 hours, return ‘XX hours’

  • If within the last 5 days, return ‘XX days’

  • If in the same year, print the date without the year

  • If in a different year, print the date with the whole year

These can be configured as options.

Examples:

yesterday = sc.datedelta(sc.now(), days=-1)
sc.elapsedtimestr(yesterday)
timedsleep(delay=None, start=None, verbose=True)[source]

Delay for a certain amount of time, to ensure accurate timing.

Parameters
  • delay (float) – time, in seconds, to wait for

  • start (float) – if provided, the start time

  • verbose (bool) – whether to print activity

Example:

for i in range(10):
    sc.timedsleep('start') # Initialize
    for j in range(int(1e6)):
        tmp = pl.rand()
    sc.timedsleep(1) # Wait for one second including computation time