2012-12-11 23:08:17 +01:00
|
|
|
import calendar
|
2020-06-11 00:54:34 +02:00
|
|
|
import datetime
|
|
|
|
|
2012-12-05 19:53:23 +01:00
|
|
|
|
2022-11-17 09:30:48 +01:00
|
|
|
class TimeZoneNotUTCError(Exception):
|
2017-10-05 00:56:30 +02:00
|
|
|
pass
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def verify_UTC(dt: datetime.datetime) -> None:
|
2020-06-05 06:55:20 +02:00
|
|
|
if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) != datetime.timezone.utc.utcoffset(dt):
|
2022-11-17 09:30:48 +01:00
|
|
|
raise TimeZoneNotUTCError(f"Datetime {dt} does not have a UTC time zone.")
|
2017-10-05 00:56:30 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def convert_to_UTC(dt: datetime.datetime) -> datetime.datetime:
|
2017-10-05 01:18:18 +02:00
|
|
|
if dt.tzinfo is None:
|
2020-06-05 06:55:20 +02:00
|
|
|
return dt.replace(tzinfo=datetime.timezone.utc)
|
|
|
|
return dt.astimezone(datetime.timezone.utc)
|
2017-10-05 01:18:18 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def floor_to_hour(dt: datetime.datetime) -> datetime.datetime:
|
2017-10-05 01:51:49 +02:00
|
|
|
verify_UTC(dt)
|
2020-06-05 06:55:20 +02:00
|
|
|
return datetime.datetime(*dt.timetuple()[:4], tzinfo=datetime.timezone.utc)
|
2016-12-20 03:34:05 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def floor_to_day(dt: datetime.datetime) -> datetime.datetime:
|
2017-10-05 01:51:49 +02:00
|
|
|
verify_UTC(dt)
|
2020-06-05 06:55:20 +02:00
|
|
|
return datetime.datetime(*dt.timetuple()[:3], tzinfo=datetime.timezone.utc)
|
analytics: Simplify frequency and measurement interval options.
Change the CountStat object to take an is_gauge variable instead of a
smallest_interval variable. Previously, (smallest_interval, frequency)
could be any of (hour, hour), (hour, day), (hour, gauge), (day, hour),
(day, day), or (day, gauge).
The current change is equivalent to excluding (hour, day) and (day, hour)
from the list above.
This change, along with other recent changes, allows us to simplify how we
handle time intervals. This commit also removes the TimeInterval object.
2016-10-14 00:15:46 +02:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def ceiling_to_hour(dt: datetime.datetime) -> datetime.datetime:
|
2017-02-28 18:39:36 +01:00
|
|
|
floor = floor_to_hour(dt)
|
|
|
|
if floor == dt:
|
2016-12-20 03:34:05 +01:00
|
|
|
return floor
|
|
|
|
return floor + datetime.timedelta(hours=1)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def ceiling_to_day(dt: datetime.datetime) -> datetime.datetime:
|
2017-02-28 18:39:36 +01:00
|
|
|
floor = floor_to_day(dt)
|
|
|
|
if floor == dt:
|
2016-12-20 03:34:05 +01:00
|
|
|
return floor
|
|
|
|
return floor + datetime.timedelta(days=1)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def timestamp_to_datetime(timestamp: float) -> datetime.datetime:
|
2020-06-05 06:55:20 +02:00
|
|
|
return datetime.datetime.fromtimestamp(float(timestamp), tz=datetime.timezone.utc)
|
2012-12-11 23:08:17 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-11-05 11:15:10 +01:00
|
|
|
def datetime_to_timestamp(dt: datetime.datetime) -> int:
|
2017-10-05 00:56:30 +02:00
|
|
|
verify_UTC(dt)
|
2017-02-28 18:39:36 +01:00
|
|
|
return calendar.timegm(dt.timetuple())
|