Skip to content

Commit

Permalink
Merge pull request #263 from azat-ch/tzlocal-4
Browse files Browse the repository at this point in the history
RFC: Add support for tzlocal 4
  • Loading branch information
xzkostyan committed Oct 29, 2021
2 parents ffa6c38 + 656456d commit d28e4b7
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 21 deletions.
11 changes: 2 additions & 9 deletions clickhouse_driver/columns/datetimecolumn.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from datetime import datetime

from pytz import timezone as get_timezone, utc
from tzlocal import get_localzone

from ..util.compat import get_localzone_name_compat
from .base import FormatColumn

EPOCH = datetime(1970, 1, 1, tzinfo=utc)
Expand Down Expand Up @@ -193,13 +192,7 @@ def create_datetime_column(spec, column_options):
offset_naive = False
else:
if not context.settings.get('use_client_time_zone', False):
try:
local_timezone = get_localzone().key
except AttributeError:
local_timezone = get_localzone().zone
except Exception:
local_timezone = None

local_timezone = get_localzone_name_compat()
if local_timezone != context.server_info.timezone:
tz_name = context.server_info.timezone

Expand Down
10 changes: 2 additions & 8 deletions clickhouse_driver/columns/numpy/datetimecolumn.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import numpy as np
import pandas as pd
from pytz import timezone as get_timezone
from tzlocal import get_localzone

from .base import NumpyColumn
from ...util.compat import get_localzone_name_compat


class NumpyDateTimeColumnBase(NumpyColumn):
Expand Down Expand Up @@ -122,16 +122,10 @@ def create_numpy_datetime_column(spec, column_options):

tz_name = timezone = None
offset_naive = True
local_timezone = None

# As Numpy do not use local timezone for converting timestamp to
# datetime we need always detect local timezone for manual converting.
try:
local_timezone = get_localzone().key
except AttributeError:
local_timezone = get_localzone().zone
except Exception:
pass
local_timezone = get_localzone_name_compat()

# Use column's timezone if it's specified.
if spec and spec[-1] == ')':
Expand Down
21 changes: 21 additions & 0 deletions clickhouse_driver/util/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,24 @@
import threading
except ImportError:
import dummy_threading as threading # noqa: F401

try:
# since tzlocal 4.0+
# this will avoid warning for get_localzone().key
from tzlocal import get_localzone_name

def get_localzone_name_compat():
try:
return get_localzone_name()
except Exception:
return None
except ImportError:
from tzlocal import get_localzone

def get_localzone_name_compat():
try:
return get_localzone().key
except AttributeError:
return get_localzone().zone
except Exception:
return None
9 changes: 7 additions & 2 deletions tests/columns/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,15 @@ def test_nullable_datetime(self):
self.assertEqual(inserted, data)

def test_handle_errors_from_tzlocal(self):
with patch('tzlocal.get_localzone') as mocked_get_localzone:
mocked_get_localzone.side_effect = UnknownTimeZoneError()
with patch('tzlocal.get_localzone') as mocked:
mocked.side_effect = UnknownTimeZoneError()
self.client.execute('SELECT now()')

if hasattr(tzlocal, 'get_localzone_name'):
with patch('tzlocal.get_localzone_name') as mocked:
mocked.side_effect = None
self.client.execute('SELECT now()')

@require_server_version(20, 1, 2)
def test_datetime64_frac_trunc(self):
with self.create_table('a DateTime64'):
Expand Down
9 changes: 7 additions & 2 deletions tests/numpy/columns/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,15 @@ def test_nullable_datetime(self):
self.assertEqual(inserted[0].dtype, object)

def test_handle_errors_from_tzlocal(self):
with patch('tzlocal.get_localzone') as mocked_get_localzone:
mocked_get_localzone.side_effect = UnknownTimeZoneError()
with patch('tzlocal.get_localzone') as mocked:
mocked.side_effect = UnknownTimeZoneError()
self.client.execute('SELECT now()')

if hasattr(tzlocal, 'get_localzone_name'):
with patch('tzlocal.get_localzone_name') as mocked:
mocked.side_effect = None
self.client.execute('SELECT now()')

@require_server_version(20, 1, 2)
def test_datetime64_frac_trunc(self):
with self.create_table('a DateTime64'):
Expand Down

0 comments on commit d28e4b7

Please sign in to comment.