Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix custom-formats with timezone #840

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions dateparser/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,29 @@ def apply_timezone(date_time, tz_string):


def apply_timezone_from_settings(date_obj, settings):
tz = get_localzone()
if settings is None:
return date_obj

if 'local' in settings.TIMEZONE.lower():
if hasattr(tz, 'localize'):
date_obj = tz.localize(date_obj)
is_originally_aware = is_aware(date_obj)

if not is_originally_aware:
if 'local' in settings.TIMEZONE.lower():
tz = get_localzone()
if hasattr(tz, 'localize'):
date_obj = tz.localize(date_obj)
else:
date_obj = date_obj.replace(tzinfo=tz)
else:
date_obj = date_obj.replace(tzinfo=tz)
else:
date_obj = localize_timezone(date_obj, settings.TIMEZONE)
date_obj = localize_timezone(date_obj, settings.TIMEZONE)

if settings.TO_TIMEZONE:
date_obj = apply_timezone(date_obj, settings.TO_TIMEZONE)

if settings.RETURN_AS_TIMEZONE_AWARE is not True:
if (
not settings.RETURN_AS_TIMEZONE_AWARE
or (settings.RETURN_AS_TIMEZONE_AWARE
and 'default' == settings.RETURN_AS_TIMEZONE_AWARE and not is_originally_aware)
):
Comment on lines +142 to +146
Copy link
Member

Choose a reason for hiding this comment

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

💄

Suggested change
if (
not settings.RETURN_AS_TIMEZONE_AWARE
or (settings.RETURN_AS_TIMEZONE_AWARE
and 'default' == settings.RETURN_AS_TIMEZONE_AWARE and not is_originally_aware)
):
if (
not settings.RETURN_AS_TIMEZONE_AWARE
or (
not is_originally_aware
and settings.RETURN_AS_TIMEZONE_AWARE == 'default'
)
):

date_obj = date_obj.replace(tzinfo=None)

return date_obj
Expand Down Expand Up @@ -235,3 +242,15 @@ def setup_logging():
},
}
logging.config.dictConfig(config)


def is_aware(date_obj):
Copy link
Member

Choose a reason for hiding this comment

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

💄 is_tz_aware or has_tz?

"""
From Python docs (https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive):

A datetime object d is aware if both of the following hold:
1. d.tzinfo is not None
2. d.tzinfo.utcoffset(d) does not return None

"""
return date_obj.tzinfo is not None and date_obj.tzinfo.utcoffset(date_obj) is not None
20 changes: 19 additions & 1 deletion tests/test_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import unittest
from collections import OrderedDict
from copy import copy
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone

from unittest.mock import Mock, patch
from parameterized import parameterized, param
Expand All @@ -12,6 +12,7 @@
from dateparser.date import DateData
from dateparser import date
from dateparser.conf import settings
from dateparser.timezone_parser import StaticTzInfo

from tests import BaseTestCase

Expand Down Expand Up @@ -258,6 +259,23 @@ def test_should_parse_date(self, date_string, date_formats, expected_result):
self.then_parsed_period_is('day')
self.then_parsed_date_is(expected_result)

@parameterized.expand([
param(date_string='Fri Jan 26 16:32:21 +0000 2018', date_formats=['%a %b %d %H:%M:%S %z %Y'],
expected_result=datetime(2018, 1, 26, 16, 32, 21)),
param(date_string='15/04/1904 14:05 +0004', date_formats=['%d/%m/%Y %H:%M %z'],
expected_result=datetime(1904, 4, 15, 14, 5, tzinfo=timezone(timedelta(0, 240)))),
param(
date_string='20-05-1994 23:00 GMT', date_formats=['%d-%m-%Y %H:%M %Z'], expected_result=datetime(
1994, 5, 20, 23, 0, tzinfo=StaticTzInfo('GMT', timedelta(seconds=0))
)
),
])
def test_should_parse_localized_dates(self, date_string, date_formats, expected_result):
self.when_date_is_parsed_with_formats(date_string, date_formats)
self.then_date_was_parsed()
self.then_parsed_period_is('day')
self.then_parsed_date_is(expected_result)

Copy link
Member

Choose a reason for hiding this comment

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

Are these tests complete enough?

Given the changes I would expect a test where the date contains a timezone, settings specify a different timezone, and we check that the parsed timezone is the one from the input string, and not the one from the settings.

Also a test about the change to if settings.RETURN_AS_TIMEZONE_AWARE is not True:.

@parameterized.expand([
param(date_string='09.16', date_formats=['%m.%d'], expected_month=9, expected_day=16),
])
Expand Down