flexmeasures.utils.time_utils

Utils for dealing with time

Functions

flexmeasures.utils.time_utils.apply_offset_chain(dt: pd.Timestamp | datetime, offset_chain: str) pd.Timestamp | datetime

Apply an offset chain to a date.

An offset chain consist of multiple (pandas) offset strings separated by commas. Moreover, this function implements the offset string “DB”, which stands for Day Begin, to get a date from a datetime, i.e. removing time details finer than a day.

Args:

dt (pd.Timestamp | datetime) offset_chain (str)

Returns:

pd.Timestamp | datetime (same type as given dt)

flexmeasures.utils.time_utils.as_server_time(dt: datetime) datetime

The datetime represented in the timezone of the FlexMeasures platform. If dt is naive, we assume it is UTC time.

flexmeasures.utils.time_utils.decide_resolution(start: datetime | None, end: datetime | None) str

Decide on a practical resolution given the length of the selected time period. Useful for querying or plotting.

flexmeasures.utils.time_utils.determine_minimum_resampling_resolution(event_resolutions: list[timedelta], fallback_resolution: timedelta = datetime.timedelta(0)) timedelta

Return minimum non-zero event resolution, or return the fallback_resolution if none of the event resolutions is non-zero.

Parameters:

fallback_resolution – Resolution to fall back on in case of no non-zero event resolutions, defaults to 0 hours.

flexmeasures.utils.time_utils.duration_isoformat(duration: timedelta)

Adapted version of isodate.duration_isoformat for formatting a datetime.timedelta.

The difference is that absolute days are not formatted as nominal days. Workaround for https://github.com/gweis/isodate/issues/74.

flexmeasures.utils.time_utils.ensure_local_timezone(dt: pd.Timestamp | datetime, tz_name: str = 'Europe/Amsterdam') pd.Timestamp | datetime

If no timezone is given, assume the datetime is in the given timezone and make it explicit. Otherwise, if a timezone is given, convert to that timezone.

flexmeasures.utils.time_utils.forecast_horizons_for(resolution: str | timedelta) list[str] | list[timedelta]

Return a list of horizons that are supported per resolution. Return values or of the same type as the input.

flexmeasures.utils.time_utils.get_first_day_of_next_month() datetime
flexmeasures.utils.time_utils.get_max_planning_horizon(resolution: timedelta) timedelta | None

Determine the maximum planning horizon for the given sensor resolution.

flexmeasures.utils.time_utils.get_most_recent_clocktime_window(window_size_in_minutes: int, now: datetime | None = None, grace_period_in_seconds: int | None = 0) tuple[datetime, datetime]

Calculate a recent time window, returning a start and end minute so that a full hour can be filled with such windows, e.g.:

Calling this function at 15:01:xx with window size 5 -> (14:55:00, 15:00:00) Calling this function at 03:36:xx with window size 15 -> (03:15:00, 03:30:00)

We can demand a grace period (of x seconds) to have passed before we are ready to accept that we’re in a new window: Calling this function at 15:00:16 with window size 5 and grace period of 30 seconds -> (14:50:00, 14:55:00)

window_size_in_minutes is assumed to > 0 and < = 60, and a divisor of 60 (1, 2, …, 30, 60).

If now is not given, the current server time is used. if now / the current time lies within a boundary minute (e.g. 15 when window_size_in_minutes=5), then the window is not deemed over and the previous one is returned (in this case, [5, 10])

Returns two datetime objects. They’ll be in the timezone (if given) of the now parameter, or in the server timezone (see FLEXMEASURES_TIMEZONE setting).

flexmeasures.utils.time_utils.get_most_recent_hour() datetime
flexmeasures.utils.time_utils.get_most_recent_quarter() datetime
flexmeasures.utils.time_utils.get_timezone(of_user=False) BaseTzInfo

Return the FlexMeasures timezone, or if desired try to return the timezone of the current user.

flexmeasures.utils.time_utils.localized_datetime(dt: datetime) datetime

Localise a datetime to the timezone of the FlexMeasures platform. Note: this will change nothing but the tzinfo field.

flexmeasures.utils.time_utils.localized_datetime_str(dt: datetime, dt_format: str = '%Y-%m-%d %I:%M %p') str

Localise a datetime to the timezone of the FlexMeasures platform. If no datetime is passed in, use server_now() as basis.

Hint: This can be set as a jinja filter, so we can display local time in the app, e.g.: app.jinja_env.filters[‘localized_datetime’] = localized_datetime_str

flexmeasures.utils.time_utils.naive_utc_from(dt: datetime) datetime

Return a naive datetime, that is localised to UTC if it has a timezone. If dt is naive, we assume it is already in UTC time.

flexmeasures.utils.time_utils.naturalized_datetime_str(dt: datetime | str | None, now: datetime | None = None) str

Naturalise a datetime object (into a human-friendly string). The dt parameter (as well as the now parameter if you use it) can be either naive or tz-aware. We assume UTC in the naive case. If dt parameter is a string it is expected to look like ‘Sun, 28 Apr 2024 08:55:58 GMT’. String format is supported for case when we make json from internal api response e.g ui/crud/users auditlog router

We use the humanize library to generate a human-friendly string. If dt is not longer ago than 24 hours, we use humanize.naturaltime (e.g. “3 hours ago”), otherwise humanize.naturaldate (e.g. “one week ago”)

Hint: This can be set as a jinja filter, so we can display local time in the app, e.g.: app.jinja_env.filters[‘naturalized_datetime’] = naturalized_datetime_str

flexmeasures.utils.time_utils.normalize_ttl(value, default: timedelta) timedelta

Normalize a TTL (time-to-live) configuration value into a datetime.timedelta.

Supported input types: - datetime.timedelta: returned as-is - int: interpreted as number of days, -1 means persist forever - ISO-8601 duration string (e.g., “P2D”, “PT12H”): parsed into a timedelta - None: defaults to the given default value

Raises:

TypeError: if the input value is not one of the supported types

This ensures that all TTL values used in the application are consistently represented as timedelta, avoiding type errors at runtime.

flexmeasures.utils.time_utils.resolution_to_hour_factor(resolution: str | timedelta) float

Return the factor with which a value needs to be multiplied in order to get the value per hour, e.g. 10 MW at a resolution of 15min are 2.5 MWh per time step.

Parameters:

resolution – timedelta or pandas offset such as “15min” or “h”

flexmeasures.utils.time_utils.round_to_closest_hour(dt: datetime) datetime
flexmeasures.utils.time_utils.round_to_closest_quarter(dt: datetime) datetime
flexmeasures.utils.time_utils.server_now() datetime

The current time (timezone aware), converted to the timezone of the FlexMeasures platform.

flexmeasures.utils.time_utils.supported_horizons() list[timedelta]
flexmeasures.utils.time_utils.timedelta_to_pandas_freq_str(resolution: timedelta) str
flexmeasures.utils.time_utils.to_http_time(dt: pd.Timestamp | datetime) str

Formats datetime using the Internet Message Format fixdate.

>>> to_http_time(pd.Timestamp("2022-12-13 14:06:23Z"))
'Tue, 13 Dec 2022 14:06:23 GMT'

References

IMF-fixdate: https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1

flexmeasures.utils.time_utils.to_utc_timestamp(value)

Convert a datetime object or string to a UTC timestamp (seconds since epoch).

The dt parameter can be either naive or tz-aware. We assume UTC in the naive case. If dt parameter is a string, it is expected to look like ‘Sun, 28 Apr 2024 08:55:58 GMT’. String format is supported for cases when we process JSON from internal API responses, e.g., ui/crud/users auditlog router.

Returns: - Float: seconds since Unix epoch (1970-01-01 00:00:00 UTC) - None: if input is None

Hint: This can be set as a jinja filter to display UTC timestamps in the app, e.g.: app.jinja_env.filters[‘to_utc_timestamp’] = to_utc_timestamp

Example usage: >>> to_utc_timestamp(datetime(2024, 4, 28, 8, 55, 58)) 1714294558.0 >>> to_utc_timestamp(“Sun, 28 Apr 2024 08:55:58 GMT”) 1714294558.0 >>> to_utc_timestamp(None)

flexmeasures.utils.time_utils.tz_index_naively(data: pd.DataFrame | pd.Series | pd.DatetimeIndex) pd.DataFrame | pd.Series | pd.DatetimeIndex

Turn any DatetimeIndex into a tz-naive one, then return. Useful for bokeh, for instance.