Skip to content

Time Parser

IOTimeParser

Collection of classmethods to parse a given date time string. The string can contain an absolute date and time, or a date and time that are relative to another time or even each other.

is_relative(input_str) classmethod

Check if the given string is a relative time (e.g. '+1d', '-8h', '-1w 08:00')

Parameters:

Name Type Description Default
input_str str

String to be checked if in relative time format

required

Returns:

Type Description
bool

True if the provided string is in relative time format

Source code in trace/utilities/time_parser.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@classmethod
def is_relative(cls, input_str: str) -> bool:
    """Check if the given string is a relative time (e.g. '+1d',
    '-8h', '-1w 08:00')

    Parameters
    ----------
    input_str : str
        String to be checked if in relative time format

    Returns
    -------
    bool
        True if the provided string is in relative time format
    """
    found = cls.full_relative_re.fullmatch(input_str)
    return bool(found)

is_absolute(input_str) classmethod

Check if the given string is an absolute time (e.g. '2024-07-16 08:00')

Parameters:

Name Type Description Default
input_str str

String to be checked if in absolute time format

required

Returns:

Type Description
bool

True if the provided string is in absolute time format

Source code in trace/utilities/time_parser.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@classmethod
def is_absolute(cls, input_str: str) -> bool:
    """Check if the given string is an absolute time (e.g.
    '2024-07-16 08:00')

    Parameters
    ----------
    input_str : str
        String to be checked if in absolute time format

    Returns
    -------
    bool
        True if the provided string is in absolute time format
    """
    found = cls.full_absolute_re.fullmatch(input_str)
    return bool(found)

relative_to_delta(time) classmethod

Convert the given string containing a relative time into a datetime.timedelta

Parameters:

Name Type Description Default
time str

String consisting of a time in a relative format (e.g. '-1d')

required

Returns:

Type Description
timedelta

A duration expressing the difference between two datetimes

Source code in trace/utilities/time_parser.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
@classmethod
def relative_to_delta(cls, time: str) -> datetime.timedelta:
    """Convert the given string containing a relative time into a
    datetime.timedelta

    Parameters
    ----------
    time : str
        String consisting of a time in a relative format (e.g. '-1d')

    Returns
    -------
    datetime.timedelta
        A duration expressing the difference between two datetimes
    """
    td = datetime.timedelta()
    negative = True
    for token in cls.relative_re.findall(time):
        logger.debug(f"Processing relative time token: {token}")
        if token[0] in "+-":
            negative = token[0] == "-"
        elif negative:
            token = "-" + token
        number = int(token[:-1])

        unit = token[-1]
        if unit == "s":
            td += datetime.timedelta(seconds=number)
        elif unit == "m":
            td += datetime.timedelta(minutes=number)
        elif unit == "H":
            td += datetime.timedelta(hours=number)
        elif unit == "w":
            td += datetime.timedelta(weeks=number)
        elif unit in "yMd":
            if unit == "y":
                number *= 365
            elif unit == "M":
                number *= 30
            td += datetime.timedelta(days=number)
    logger.debug(f"Relative time '{time}' as delta: {td}")
    return td

set_time_on_datetime(dt, time_str) classmethod

Set an absolute time on a datetime object

Parameters:

Name Type Description Default
dt datetime

The datetime to alter

required
time_str str

The string containing the new time to set (e.g. '-1d 15:00')

required

Returns:

Type Description
datetime

The datetime object with the same date and the new time

Source code in trace/utilities/time_parser.py
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
@classmethod
def set_time_on_datetime(cls, dt: datetime.datetime, time_str: str) -> datetime.datetime:
    """Set an absolute time on a datetime object

    Parameters
    ----------
    dt : datetime
        The datetime to alter
    time_str : str
        The string containing the new time to set (e.g. '-1d 15:00')

    Returns
    -------
    datetime
        The datetime object with the same date and the new time
    """
    # Get absolute time from string, return datetime if none
    try:
        time = cls.time_re.search(time_str).group()
    except AttributeError:
        return dt

    if time.count(":") == 1:
        time += ":00"
    h, m, s = map(int, map(float, time.split(":")))
    dt = dt.replace(hour=h, minute=m, second=s)

    return dt

parse_times(start_str, end_str) classmethod

Convert 2 strings containing a start and end date & time, return the values' datetime objects. The strings can be formatted as either absolute times or relative times. Both are needed as relative times may be relative to the other time.

Parameters:

Name Type Description Default
start_str str

The leftmost time the x-axis of the plot should show

required
end_str str

The rigthmost time the x-axis of the plot should show, should be >start

required

Returns:

Type Description
tuple[datetime, datetime]

The python datetime objects for the exact start and end datetimes referenced

Raises:

Type Description
ValueError

One of the given strings is in an incorrect format

Source code in trace/utilities/time_parser.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
@classmethod
def parse_times(cls, start_str: str, end_str: str) -> tuple[datetime.datetime, datetime.datetime]:
    """Convert 2 strings containing a start and end date & time, return the
    values' datetime objects. The strings can be formatted as either absolute
    times or relative times. Both are needed as relative times may be relative
    to the other time.

    Parameters
    ----------
    start_str : str
        The leftmost time the x-axis of the plot should show
    end_str : str
        The rigthmost time the x-axis of the plot should show, should be >start

    Returns
    -------
    tuple[datetime, datetime]
        The python datetime objects for the exact start and end datetimes referenced

    Raises
    ------
    ValueError
        One of the given strings is in an incorrect format
    """
    start_dt = start_delta = None
    end_dt = end_delta = None
    basetime = datetime.datetime.now()

    # Process the end time string first to determine
    # if the basetime is the start time, end time, or 'now'
    if end_str == "now":
        end_dt = basetime
    elif cls.is_relative(end_str):
        end_delta = cls.relative_to_delta(end_str)

        # end_delta >= 0 --> the basetime is start time, so are processed after the start time
        # end_delta <  0 --> the basetime is 'now'
        if end_delta < datetime.timedelta():
            end_dt = basetime + end_delta
            end_dt = cls.set_time_on_datetime(end_dt, end_str)
    elif cls.is_absolute(end_str):
        end_dt = datetime.datetime.fromisoformat(end_str)
        basetime = end_dt
    else:
        raise ValueError("Time Axis end value is in an unexpected format.")

    # Process the start time string second, it may be used as the basetime
    if cls.is_relative(start_str):
        start_delta = cls.relative_to_delta(start_str)

        # start_delta >= 0 --> raise ValueError; this isn't allowed
        if start_delta < datetime.timedelta():
            start_dt = basetime + start_delta
            start_dt = cls.set_time_on_datetime(start_dt, start_str)
        else:
            raise ValueError("Time Axis start value cannot be a relative time and be positive.")
    elif cls.is_absolute(start_str):
        start_dt = datetime.datetime.fromisoformat(start_str)
    else:
        raise ValueError("Time Axis start value is in an unexpected format.")

    # If the end time is relative and end_delta >= 0 --> start time is the base
    if end_delta and end_delta >= datetime.timedelta():
        basetime = start_dt
        end_dt = end_delta + basetime
        end_dt = cls.set_time_on_datetime(end_dt, end_str)

    return (start_dt, end_dt)