Skip to content

Commit

Permalink
Added get_tzinfo function in dtime API
Browse files Browse the repository at this point in the history
  • Loading branch information
xispa committed May 17, 2023
1 parent 0aed612 commit 5e4f661
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 9 deletions.
35 changes: 26 additions & 9 deletions src/senaite/core/api/dtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def to_ansi(dt, show_time=True):


def get_timezone(dt, default="Etc/GMT"):
"""Get a valid pytz timezone of the datetime object
"""Get a valid pytz timezone name of the datetime object
:param dt: date object
:returns: timezone as string, e.g. Etc/GMT or CET
Expand Down Expand Up @@ -238,6 +238,29 @@ def get_timezone(dt, default="Etc/GMT"):
return tz


def get_tzinfo(dt_tz, default=pytz.UTC):
"""Returns the valid pytz tinfo from the date or timezone name
Returns the default timezone info if date does not have a valid timezone
set or is TZ-naive
:param dt: timezone name or date object to extract the tzinfo
:type dt: str/date/datetime/DateTime
:param: default: timezone name or pytz tzinfo object
:returns: pytz tzinfo object, e.g. `<UTC>, <StaticTzInfo 'Etc/GMT+2'>
:rtype: UTC/BaseTzInfo/StaticTzInfo/DstTzInfo
"""
if is_str(default):
default = pytz.timezone(default)
try:
if is_str(dt_tz):
return pytz.timezone(dt_tz)
tz = get_timezone(dt_tz, default=default.zone)
return pytz.timezone(tz)
except pytz.UnknownTimeZoneError:
return default


def is_valid_timezone(timezone):
"""Checks if the timezone is a valid pytz/Olson name
Expand Down Expand Up @@ -445,9 +468,9 @@ def get_relative_delta(dt1, dt2=None):
If `dt2` is None, the current datetime is used.
:param dt1: the first date/time to compare
:type dt1: str/date/datetime/DateTime
:type dt1: string/date/datetime/DateTime
:param dt2: the second date/time to compare
:type dt2: str/date/datetime/DateTime
:type dt2: string/date/datetime/DateTime
:returns: interval of time (e.g. `relativedelta(hours=+3)`)
:rtype: dateutil.relativedelta
"""
Expand All @@ -459,12 +482,6 @@ def get_relative_delta(dt1, dt2=None):
if not all([dt1, dt2]):
return None

def get_tzinfo(dt, default=pytz.UTC):
try:
return pytz.timezone(get_timezone(dt))
except pytz.UnknownTimeZoneError:
return default

naives = [is_timezone_naive(dt) for dt in [dt1, dt2]]
if all(naives):
# Both naive, no need to do anything special
Expand Down
68 changes: 68 additions & 0 deletions src/senaite/core/tests/doctests/API_datetime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,74 @@ Get the timezone from `datetime.date` objects:
'Etc/GMT'


Get the timezone info
.....................

Get the timezone info from TZ name:

>>> dtime.get_tzinfo("Etc/GMT")
<StaticTzInfo 'Etc/GMT'>

>>> dtime.get_tzinfo("Pacific/Fiji")
<DstTzInfo 'Pacific/Fiji' LMT+11:56:00 STD>

>>> dtime.get_tzinfo("UTC")
<UTC>

Get the timezone info from `DateTime` objects:

>>> dtime.get_tzinfo(DateTime("2022-02-25"))
<StaticTzInfo 'Etc/GMT'>

>>> dtime.get_tzinfo(DateTime("2022-02-25 12:00 GMT+2"))
<StaticTzInfo 'Etc/GMT-2'>

>>> dtime.get_tzinfo(DateTime("2022-02-25 12:00 GMT-2"))
<StaticTzInfo 'Etc/GMT+2'>

Get the timezone info from `datetime.datetime` objects:

>>> DATE = "2021-12-24 12:00"
>>> dt = datetime.strptime(DATE, DATEFORMAT)
>>> dtime.get_tzinfo(dt)
<UTC>

>>> dtime.get_tzinfo(dtime.to_zone(dt, "Europe/Berlin"))
<DstTzInfo 'CET' CET+1:00:00 STD>

Get the timezone info from `datetime.date` objects:

>>> dtime.get_tzinfo(dt.date)
<UTC>

Getting the timezone info from a naive date returns default timezone info:

>>> dt_naive = dt.replace(tzinfo=None)
>>> dtime.get_tzinfo(dt_naive)
<UTC>

>>> dtime.get_tzinfo(dt_naive, default="Pacific/Fiji")
<DstTzInfo 'Pacific/Fiji' LMT+11:56:00 STD>

We can use a timezone info as the default parameter as well:

>>> dtime.get_tzinfo(dt_naive, default=dtime.pytz.UTC)
<UTC>

Default can also be a timezone name:

>>> dtime.get_tzinfo(dt_naive, default="America/Port_of_Spain")
<DstTzInfo 'America/Port_of_Spain' LMT-1 day, 19:36:00 STD>

And an error is rised if default is not a valid timezone, even if the date
passed-in is valid:

>>> dtime.get_tzinfo(dt_naive, default="Atlantida")
Traceback (most recent call last):
...
UnknownTimeZoneError: 'Atlantida'


Check if timezone is valid
..........................

Expand Down

0 comments on commit 5e4f661

Please sign in to comment.