diff --git a/cl_sii/libs/tz_utils.py b/cl_sii/libs/tz_utils.py index 8c6ec286..9d420f07 100644 --- a/cl_sii/libs/tz_utils.py +++ b/cl_sii/libs/tz_utils.py @@ -1,3 +1,15 @@ +""" +Timezone utils +============== + + +Naive and aware +--------------- + +These concept are defined in Python standard library module datetime +`docs `_. + +""" from datetime import datetime from typing import Union @@ -14,8 +26,12 @@ ] -UTC = pytz.UTC # type: PytzTimezone -TIMEZONE_CL_SANTIAGO = pytz.timezone('America/Santiago') # type: PytzTimezone +TZ_UTC = pytz.UTC # type: PytzTimezone +TZ_CL_SANTIAGO = pytz.timezone('America/Santiago') # type: PytzTimezone + +# TODO: remove +UTC = TZ_UTC +TIMEZONE_CL_SANTIAGO = TZ_CL_SANTIAGO def get_now_tz_aware() -> datetime: @@ -31,7 +47,7 @@ def get_now_tz_aware() -> datetime: # - `pytz.UTC.localize(datetime.utcnow())` # source: 'django.utils.timezone.now' @ Django 2.1.3 - return datetime.utcnow().replace(tzinfo=UTC) + return datetime.utcnow().replace(tzinfo=TZ_UTC) def convert_naive_dt_to_tz_aware(dt: datetime, tz: PytzTimezone) -> datetime: @@ -44,13 +60,13 @@ def convert_naive_dt_to_tz_aware(dt: datetime, tz: PytzTimezone) -> datetime: >>> dt_naive.isoformat() '2018-10-23T01:54:13' - >>> dt_tz_aware_1 = convert_naive_dt_to_tz_aware(dt_naive, UTC) + >>> dt_tz_aware_1 = convert_naive_dt_to_tz_aware(dt_naive, TZ_UTC) >>> dt_tz_aware_1 datetime.datetime(2018, 10, 23, 1, 54, 13, tzinfo=) >>> dt_tz_aware_1.isoformat() '2018-10-23T04:54:13+00:00' - >>> dt_tz_aware_2 = convert_naive_dt_to_tz_aware(dt_naive, TIMEZONE_CL_SANTIAGO) + >>> dt_tz_aware_2 = convert_naive_dt_to_tz_aware(dt_naive, TZ_CL_SANTIAGO) >>> dt_tz_aware_2 datetime.datetime(2018, 10, 23, 1, 54, 13, tzinfo=) @@ -64,3 +80,41 @@ def convert_naive_dt_to_tz_aware(dt: datetime, tz: PytzTimezone) -> datetime: """ dt_tz_aware = tz.localize(dt) # type: datetime return dt_tz_aware + + +def dt_is_aware(value: datetime) -> bool: + """ + Return whether datetime ``value`` is "aware". + + >>> dt_naive = datetime(2018, 10, 23, 1, 54, 13) + >>> dt_is_aware(dt_naive) + False + >>> dt_is_aware(convert_naive_dt_to_tz_aware(dt_naive, TZ_UTC)) + True + >>> dt_is_aware(convert_naive_dt_to_tz_aware(dt_naive, TZ_CL_SANTIAGO)) + True + + """ + if not isinstance(value, datetime): + raise TypeError + # source: 'django.utils.timezone.is_aware' @ Django 2.1.7 + return value.utcoffset() is not None + + +def dt_is_naive(value: datetime) -> bool: + """ + Return whether datetime ``value`` is "naive". + + >>> dt_naive = datetime(2018, 10, 23, 1, 54, 13) + >>> dt_is_naive(dt_naive) + True + >>> dt_is_naive(convert_naive_dt_to_tz_aware(dt_naive, TZ_UTC)) + False + >>> dt_is_naive(convert_naive_dt_to_tz_aware(dt_naive, TZ_CL_SANTIAGO)) + False + + """ + if not isinstance(value, datetime): + raise TypeError + # source: 'django.utils.timezone.is_naive' @ Django 2.1.7 + return value.utcoffset() is None diff --git a/cl_sii/rcv/parse.py b/cl_sii/rcv/parse.py index 0e5547d9..8f22786a 100644 --- a/cl_sii/rcv/parse.py +++ b/cl_sii/rcv/parse.py @@ -76,7 +76,7 @@ class _RcvCsvDialect(csv.Dialect): class RcvCsvRowSchema(marshmallow.Schema): EXPECTED_INPUT_FIELDS = tuple(_RCV_CSV_EXPECTED_FIELD_NAMES) + (_CSV_ROW_DICT_EXTRA_FIELDS_KEY, ) # type: ignore # noqa: E501 - FIELD_FECHA_RECEPCION_DATETIME_TZ = tz_utils.TIMEZONE_CL_SANTIAGO + FIELD_FECHA_RECEPCION_DATETIME_TZ = tz_utils.TZ_CL_SANTIAGO class Meta: strict = True diff --git a/tests/test_libs_tz_utils.py b/tests/test_libs_tz_utils.py index 8d2bcb32..4fe2145b 100644 --- a/tests/test_libs_tz_utils.py +++ b/tests/test_libs_tz_utils.py @@ -1,16 +1,29 @@ import unittest -from cl_sii.libs.tz_utils import convert_naive_dt_to_tz_aware, get_now_tz_aware # noqa: F401 +from cl_sii.libs.tz_utils import ( # noqa: F401 + convert_naive_dt_to_tz_aware, dt_is_aware, dt_is_naive, get_now_tz_aware, + PytzTimezone, TZ_CL_SANTIAGO, TZ_UTC, +) class FunctionsTest(unittest.TestCase): def test_get_now_tz_aware(self) -> None: - # TODO: implement! + # TODO: implement for 'get_now_tz_aware' # Reuse doctests/examples in function docstring. pass def test_convert_naive_dt_to_tz_aware(self) -> None: - # TODO: implement! + # TODO: implement for 'convert_naive_dt_to_tz_aware' + # Reuse doctests/examples in function docstring. + pass + + def test_dt_is_aware(self) -> None: + # TODO: implement for 'dt_is_aware' + # Reuse doctests/examples in function docstring. + pass + + def test_dt_is_naive(self) -> None: + # TODO: implement for 'dt_is_naive' # Reuse doctests/examples in function docstring. pass