Skip to content

Commit

Permalink
Fix issue #1011 with timezone conversion (from Windows timezones to I…
Browse files Browse the repository at this point in the history
…ANA ones) using the python 3.9 ZoneInfo objects
  • Loading branch information
Alejandro Casanovas committed Feb 1, 2024
1 parent 4c10aed commit fd97b0f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
22 changes: 14 additions & 8 deletions O365/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from requests_oauthlib import OAuth2Session
from stringcase import pascalcase, camelcase, snakecase
from tzlocal import get_localzone
from zoneinfo import ZoneInfoNotFoundError
from zoneinfo import ZoneInfoNotFoundError, ZoneInfo
from .utils import ME_RESOURCE, BaseTokenBackend, FileSystemTokenBackend, Token
import datetime as dt

Expand Down Expand Up @@ -96,13 +96,19 @@ def __init__(self, *, protocol_url=None, api_version=None,
self.default_resource = default_resource or ME_RESOURCE
self.use_default_casing = True if casing_function is None else False
self.casing_function = casing_function or camelcase
if timezone and isinstance(timezone, str):
timezone = dt.timezone(timezone)
try:
self.timezone = timezone or get_localzone()
except ZoneInfoNotFoundError as e:
log.debug('Timezone not provided and the local timezone could not be found. Default to UTC.')
self.timezone = dt.timezone.utc
if timezone:
if isinstance(timezone, str):
# convert string to ZoneInfo
try:
timezone = ZoneInfo(timezone)
except ZoneInfoNotFoundError:
log.debug(f'Timezone {timezone} could not be found. Will default to UTC.')
timezone = ZoneInfo('UTC')
else:
if not isinstance(timezone, ZoneInfo):
raise ValueError(f'The timezone parameter must be either a string or a valid ZoneInfo instance.')
# get_localzone() from tzlocal will try to get the system local timezone and if not will return UTC
self.timezone = timezone or get_localzone()
self.max_top_value = 500 # Max $top parameter value

# define any keyword that can be different in this protocol
Expand Down
5 changes: 2 additions & 3 deletions O365/utils/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import datetime as dt
from zoneinfo import ZoneInfoNotFoundError
import logging
from collections import OrderedDict
from enum import Enum
import zoneinfo
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from dateutil.parser import parse
from stringcase import snakecase
Expand Down Expand Up @@ -431,7 +430,7 @@ def _parse_date_time_time_zone(self, date_time_time_zone, is_all_day=False):
local_tz = self.protocol.timezone
if isinstance(date_time_time_zone, dict):
try:
timezone = zoneinfo.ZoneInfo(
timezone = ZoneInfo(
get_iana_tz(date_time_time_zone.get(self._cc('timeZone'), 'UTC')))
except ZoneInfoNotFoundError:
timezone = local_tz
Expand Down
9 changes: 4 additions & 5 deletions O365/utils/windows_tz.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Mapping from iana timezones to windows timezones and vice versa
"""
from datetime import tzinfo
from zoneinfo import ZoneInfoNotFoundError
from zoneinfo import ZoneInfoNotFoundError, ZoneInfo

# noinspection SpellCheckingInspection
IANA_TO_WIN = {
Expand Down Expand Up @@ -628,16 +628,15 @@ def get_iana_tz(windows_tz):
return timezone


def get_windows_tz(iana_tz):
def get_windows_tz(iana_tz: ZoneInfo) -> str:
""" Returns a valid windows TimeZone from a given pytz TimeZone
(Iana/Olson Timezones)
Note: Windows Timezones are SHIT!... no ... really THEY ARE
HOLY FUCKING SHIT!.
"""
timezone = IANA_TO_WIN.get(
iana_tz.zone if isinstance(iana_tz, tzinfo) else iana_tz)
iana_tz.key if isinstance(iana_tz, tzinfo) else iana_tz)
if timezone is None:
raise ZoneInfoNotFoundError(
"Can't find Iana TimeZone " + iana_tz.zone)
raise ZoneInfoNotFoundError(f"Can't find Iana timezone {iana_tz.key}")

return timezone

4 comments on commit fd97b0f

@RogerSelwyn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think line 461 timezone = date_time.tzinfo.zone if date_time.tzinfo is not None else None of utils.py also needs changing to refer to key.

@alejcas
Copy link
Member

@alejcas alejcas commented on fd97b0f Feb 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5b06c79

@RogerSelwyn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I downloaded before that. Been fighting a python path change in Home Assistant, so took me a while. I'll re-check

@RogerSelwyn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Please sign in to comment.