Time Intervals and Time Interval Lists

Introduction

Time intervals are critical to define the start and end of certain events such as start and end of communications with a groundstation, entering and exiting the eclipse or start and end of a thruster firing. This is particularly useful when two intervals (or sets of intervals) can be evaluated through operations such as union and intersection. This enables us to answer questions such as “What are the time intervals where thruster firings occur during communications?” (an intersection operation between ‘intervals of thruster firings’ and ‘communications interval lists’) or “When can I see a satellite at night?” (an intersection operation between intervals of ‘satellite above horizon’, ‘sun below horizon’ and ‘satellite not in eclipse’).

The timeinterval module provides the basic time interval functionality with the TimeInterval class i.e., a time interval with a start and end time/date, using the high precision astropy.time.Time classes under the hood to represent time and portion.interval.Interval class to manage and manipulate the time intervals.

A TimeInterval can interact with other intervals through TimeInterval.union() and TimeInterval.intersect() methods. They can change their size through TimeInterval.expand() and they can check whether they contain (TimeInterval.contains()) or intersect with (TimeInterval.is_intersecting()) another time interval.

A list of such time intervals constitute TimeIntervalList class. A list also has a start and end of validity. This usually marks the start and end of an analysis. For example, a communications list that is valid for one day and containing no time intervals would mean that there are no communication opportunities for that day. The list can simply be inverted (TimeIntervalList.invert()) to get a list of ‘no communication duration’, which would then show a list with a single TimeInterval that spans the entire duration of validity.

Using the Basic TimeInterval Class

A TimeInterval class can be simply initialised with a start time and either with an end time (astropy.time.Time) or with a duration (astropy.time.TimeDelta). These start and end times can be retrieved by the properties TimeInterval.start() and TimeInterval.end().

from astropy.time import Time, TimeDelta
from satmad.utils.timeinterval import TimeInterval

interval_with_end_time = TimeInterval(
    Time("2020-04-11T00:00:00.000", scale="utc"),
    Time("2020-04-11T00:10:00.000", scale="utc"),
)
interval_with_duration = TimeInterval(
    Time("2020-04-11T00:00:00", scale="utc"),
    TimeDelta(60.0, format='sec'),
)

The resulting time intervals can be quickly shown as:

>>> str(interval_with_end_time)
'[ 2020-04-11T00:00:00.000  2020-04-11T00:10:00.000 ]\n'
>>> str(interval_with_duration)
'[ 2020-04-11T00:00:00.000  2020-04-11T00:01:00.000 ]\n'

The end time of the interval should be later than the start time. Otherwise, a ValueError will be raised.

The TimeInterval class can answer some questions:

Some examples are given below:

>>> interval_with_end_time.is_in_interval(Time("2020-04-11T00:05:00.000", scale="utc"))
True
>>> interval_with_end_time.is_equal(TimeInterval(Time("2020-04-09T00:00:00", scale="utc"), TimeDelta(600.0, format="sec")))
True
>>> interval_with_end_time.is_intersecting(TimeInterval(Time("2020-04-11T00:05:00", scale="utc"), TimeDelta(600.0, format="sec")))
True
>>> interval_with_end_time.contains(TimeInterval(Time("2020-04-11T00:05:00", scale="utc"), TimeDelta(60.0, format="sec")))
True
>>> interval_with_end_time.duration().sec
599.9999999999931

The intervals can be expanded or shrunk through the TimeInterval.expand() method and defining positive or negative astropy.time.TimeDelta values to modify the start and end times of the interval.

>>> str(interval_with_end_time)
'[ 2020-04-11T00:00:00.000  2020-04-11T00:10:00.000 ]\n'
>>> expanded = interval_with_end_time.expand(start_delta=TimeDelta(60.0, format="sec"), end_delta=TimeDelta(-120.0, format="sec"))
>>> str(expanded)
'[ 2020-04-10T23:59:00.000  2020-04-11T00:08:00.000 ]\n'

Time intervals can be subjected to an intersection (a new TimeInterval that is the intersection of two intervals) or union (a new TimeInterval that is the union of two intervals) operator. These operators are possible only when these two intervals have some intersection - otherwise the result will be a None.

>>> str(interval_with_end_time.union(expanded))
'[ 2020-04-10T23:59:00.000  2020-04-11T00:10:00.000 ]\n'
>>> str(interval_with_end_time.intersect(expanded))
'[ 2020-04-11T00:00:00.000  2020-04-11T00:08:00.000 ]\n'

List of time intervals: The TimeIntervalList Class

The TimeIntervalList usually will not be generated explicitly by a user, except, for example, as an external constraint such as the durations when a groundstation is not available. Usually such lists are results of certain analyses such as eclipse intervals for a location on ground or different attitude profiles for a satellite.

The TimeIntervalList class stores the TimeInterval objects as well as another TimeInterval to represent the bounds of the validity of this list. If this validity interval is not defined explicitly, then it is assumed to start with the beginning of the first TimeInterval and end with the end of the final TimeInterval.

Operations such as TimeIntervalList.intersection() and TimeIntervalList.union() are also possible for two TimeIntervalList objects. As a TimeIntervalList is defined for a certain validity interval, the union or intersection of two TimeIntervalList objects will yield another TimeIntervalList that is only valid for the intersection of validity of these two intervals.

Any interval within the list can be queried through TimeIntervalList.get_interval() method. Similarly, the TimeInterval that keeps the interval of validity can be queried through TimeIntervalList.valid_interval() property.

The TimeIntervalList will yield a new, inverted (or complementing) version of itself through the TimeIntervalList.invert() method. For example, for a single interval of [t0, t1] in a validity interval [T0,T1], the inverted interval list would be [T0,t0] and [t1,T1]. If there are no intervals, the inverse becomes the entire validity interval.

Reference/API

Time interval module.

TimeInterval class stores time intervals and TimeIntervalList class stores lists of TimeInterval objects.

class satmad.utils.timeinterval.TimeInterval(start_time, end_time, replicate=False, start_inclusive=True, end_inclusive=True)

Represent and manipulate a single time interval.

This is a thin wrapper around the portion.interval.Interval class from portion package (for the Atomic intervals), using Astropy Time classes under the hood.

property as_time

Gets the start and end intervals contained a single Time object.

contains(interval)

Checks whether the requested interval is contained within this (self) interval.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

True if check interval is contained within this interval, False otherwise

Return type

bool

property duration

Computes the duration of the interval.

Returns

duration – Duration of the interval (always positive)

Return type

TimeDelta

property end

Returns the end time of the interval.

expand(start_delta=0, end_delta=0, replicate=False, start_inclusive=True, end_inclusive=True)

Expands (or shrinks) the interval.

Generates a new, expanded (or shrunk) TimeInterval, where:

  • new interval start: interval_start - start_delta

  • new interval end: interval_end + end_delta

Negative start and/or end times are possible (to shrink the interval), though values ending in a negative interval will throw a ValueError. This method can be used to modify the ends of the interval (open or closed) as well.

Parameters
  • start_delta (TimeDelta) – The delta time to expand the start of the interval (or to shrink, with negative values)

  • end_delta (TimeDelta) – The delta time to expand the end of the interval (or to shrink, with negative values)

  • replicate (bool) – True to replicate (deep copy) the Time or TimeDelta objects, False to use a shallow copy to save memory

  • start_inclusive (bool) – True if the start of the new interval is inclusive (closed), False if exclusive (open)

  • end_inclusive (bool) – True if the start of the new interval is inclusive (closed), False if exclusive (open)

Returns

A new TimeInterval that is the result of the requested change

Return type

TimeInterval

Raises

ValueError – Raised if the requested expansion results in a negative duration interval

intersect(interval)

Intersection operator for a time interval and this time interval.

Returns a new interval that is the Intersection of two intervals, or None if there is no intersection.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

A new interval that is the Intersection of two intervals, or None if there is no intersection

Return type

TimeInterval

is_equal(interval)

Checks whether two intervals are (almost) equal in value.

If the two start or end values are as close as _EPS_TIME, then they are assumed to be equal in value.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

True if interval start and end are (almost) equal, False otherwise

Return type

bool

is_in_interval(time)

Checks whether the requested time is within the time interval.

Parameters

time (Time) – Time to be checked

Returns

True if time is within the reference interval, False otherwise

Return type

bool

is_intersecting(interval)

Checks whether the requested interval intersects (or is contained within) the reference interval.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

True if check interval intersects with the reference interval, False otherwise

Return type

bool

property p_interval

Returns the underlying Interval object.

Warning

Most users will not need to access this object. Intended for developer use only.

property start

Returns the start time of the interval.

union(interval)

Union operator for a time interval and this time interval.

Returns a new interval that is the Union of two intervals, or None if there is no intersection.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

A new interval that is the Union of two intervals, or None if there is no intersection

Return type

TimeInterval

class satmad.utils.timeinterval.TimeIntervalList(intervals, start_valid=None, end_valid=None, replicate=False)

Represent and manipulate time intervals.

This is a thin wrapper around the portion.interval.Interval class, using Astropy Time classes under the hood.

start_valid and end_valid values are used to mark the start and end of this list of time intervals. If they are not specified, the beginning and end points of the list of TimeInterval instances are used.

Parameters
  • intervals (list[TimeInterval] or None) – List of intervals

  • start_valid (Time or TimeInterval) – Time at which the validity of this TimeInterval starts (only the first instance contained in the Time object is used). If specified as TimeInterval, it is copied into this and end_valid is ignored (the only case where None is acceptable).

  • end_valid (Time, TimeDelta or None) – Time or duration at which the validity of this TimeInterval ends (only the first instance contained in the Time object is used). None is acceptable only when start_valid is defined as a TimeInterval

  • replicate (bool) – True to replicate (deep copy) the Time or TimeDelta objects, False to use a shallow copy to save memory

Raises

ValueError – Raised if init_times and end_times objects sizes mismatch.

get_interval(index)

Gets the time interval for the given index.

Parameters

index (int) – requested index

Returns

TimeInterval corresponding to the index

Return type

TimeInterval

Raises

IndexError – Requested index is out of bounds

intersect(interval)

Intersection operator for a time interval and this time interval list.

Returns a new interval that is the Intersection of the interval and the time interval list, or None if there is no intersection.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

A new interval that is the Intersection of the interval and the time interval list, or None if there is no intersection.

Return type

TimeInterval

intersect_list(interval_list)

Intersection operator for a time interval list and this time interval list.

Returns a new interval list that is the Intersection of interval_list and this time interval list, or None if there is no intersection even in the validity intervals.

Parameters

interval_list (TimeIntervalList) – Time interval list to be checked

Returns

A new interval list that is the Intersection of interval_list and this time interval list, or None if there is no intersection even in the validity intervals.

Return type

TimeIntervalList

property intervals

Gets the time intervals within this TimeIntervalList.

invert(replicate=False)

Creates an inverted (or complement) copy of this time interval list, while keeping the same validity range.

For example, for a single interval of [t0, t1] in a validity interval [T0,T1], the inverted interval list would be [T0,t0] and [t1,T1]. If there are no intervals, the inverse becomes the entire validity interval.

Parameters

replicate (bool) – True to replicate (deep copy) the Time or TimeDelta objects, False to use a shallow copy to save memory

Returns

  • A new TimeIntervalList that has the same validity range but the individual

  • intervals are inverted.

is_in_interval(time)

Checks whether the requested time is within the time interval list.

Parameters

time (Time) – Time to be checked

Returns

True if time is within the interval list, False otherwise. Also returns False if requested time is outside validity interval.

Return type

bool

is_intersecting(interval)

Checks whether the requested interval intersects (or is contained within) the interval list.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

True if check interval intersects with the interval list, False otherwise

Return type

bool

union(interval)

Union operator for a time interval and this time interval list.

Returns a new interval that is the Union of the interval and the time interval list, or None if there is no intersection.

Parameters

interval (TimeInterval) – Time interval to be checked

Returns

A new interval that is the Union of the interval and the time interval list, or None if there is no intersection.

Return type

TimeInterval

union_list(interval_list)

Union operator for a time interval list and this time interval list.

Returns a new interval list that is the Union of interval_list and this time interval list, or None if there is no intersection even in the validity intervals.

Parameters

interval_list (TimeIntervalList) – Time interval list to be checked

Returns

A new interval list that is the Union of interval_list and this time interval list, or None if there is no intersection.

Return type

TimeIntervalList

property valid_interval

Gets the time interval of validity for the TimeIntervalList.