1# -*- coding: utf-8 -*-
2from __future__ import unicode_literals
3
4from parameterized import parameterized, param
5from datetime import datetime, tzinfo
6
7from tests import BaseTestCase
8
9from dateparser.conf import settings
10from dateparser.conf import apply_settings
11
12from dateparser import parse
13
14
15def test_function(settings=None):
16    return settings
17
18
19class TimeZoneSettingsTest(BaseTestCase):
20    def setUp(self):
21        super(TimeZoneSettingsTest, self).setUp()
22        self.given_ds = NotImplemented
23        self.result = NotImplemented
24        self.timezone = NotImplemented
25        self.confs = NotImplemented
26
27    @parameterized.expand([
28        param('12 Feb 2015 10:30 PM +0100', datetime(2015, 2, 12, 22, 30), 'UTC\+01:00'),
29        param('12 Feb 2015 4:30 PM EST', datetime(2015, 2, 12, 16, 30), 'EST'),
30        param('12 Feb 2015 8:30 PM PKT', datetime(2015, 2, 12, 20, 30), 'PKT'),
31        param('12 Feb 2015 8:30 PM ACT', datetime(2015, 2, 12, 20, 30), 'ACT'),
32        ])
33    def test_should_return_and_assert_tz(self, ds, dt, tz):
34        self.given(ds)
35        self.given_configurations({})
36        self.when_date_is_parsed()
37        self.then_date_is_tz_aware()
38        self.then_date_is(dt)
39        self.then_timezone_is(tz)
40
41    @parameterized.expand([
42        param('12 Feb 2015 4:30 PM EST', datetime(2015, 2, 12, 16, 30), 'EST'),
43        param('12 Feb 2015 8:30 PM PKT', datetime(2015, 2, 12, 20, 30), 'PKT'),
44        param('12 Feb 2015 8:30 PM ACT', datetime(2015, 2, 12, 20, 30), 'ACT'),
45        param('12 Feb 2015 8:30 PM', datetime(2015, 2, 12, 20, 30), ''),
46        ])
47    def test_only_return_explicit_timezone(self, ds, dt, tz):
48        self.given(ds)
49        self.given_configurations({})
50        self.when_date_is_parsed()
51        self.then_date_is(dt)
52        if tz:
53            self.then_date_is_tz_aware()
54            self.then_timezone_is(tz)
55        else:
56            self.then_date_is_not_tz_aware()
57
58    @parameterized.expand([
59        param('12 Feb 2015 4:30 PM EST', datetime(2015, 2, 12, 16, 30),),
60        param('12 Feb 2015 8:30 PM PKT', datetime(2015, 2, 12, 20, 30),),
61        param('12 Feb 2015 8:30 PM ACT', datetime(2015, 2, 12, 20, 30),),
62        param('12 Feb 2015 8:30 PM +0100', datetime(2015, 2, 12, 20, 30),),
63        ])
64    def test_should_return_naive_if_RETURN_AS_TIMEZONE_AWARE_IS_FALSE(self, ds, dt):
65        self.given(ds)
66        self.given_configurations({'RETURN_AS_TIMEZONE_AWARE': False})
67        self.when_date_is_parsed()
68        self.then_date_is(dt)
69        self.then_date_is_not_tz_aware()
70
71    def then_timezone_is(self, tzname):
72        self.assertEqual(self.result.tzinfo.tzname(''), tzname)
73
74    def given(self, ds):
75        self.given_ds = ds
76
77    def given_configurations(self, confs):
78        if 'TIMEZONE' not in confs:
79            confs.update({'TIMEZONE': 'local'})
80
81        self.confs = settings.replace(**confs)
82
83    def when_date_is_parsed(self):
84        self.result = parse(self.given_ds, settings=(self.confs or {}))
85
86    def then_date_is_tz_aware(self):
87        self.assertIsInstance(self.result.tzinfo, tzinfo)
88
89    def then_date_is_not_tz_aware(self):
90        self.assertIsNone(self.result.tzinfo)
91
92    def then_date_is(self, date):
93        dtc = self.result.replace(tzinfo=None)
94        self.assertEqual(dtc, date)
95
96
97class SettingsTest(BaseTestCase):
98
99    def setUp(self):
100        super(SettingsTest, self).setUp()
101        self.default_settings = settings
102
103    def test_apply_settings_should_return_default_settings_when_no_settings_are_supplied_to_the_decorated_function(self):
104        test_func = apply_settings(test_function)
105        self.assertEqual(test_func(), self.default_settings)
106
107    def test_apply_settings_should_return_non_default_settings_when_settings_are_supplied_to_the_decorated_function(self):
108        test_func = apply_settings(test_function)
109        self.assertNotEqual(test_func(settings={'PREFER_DATES_FROM': 'past'}), self.default_settings)
110
111    def test_apply_settings_should_not_create_new_settings_when_same_settings_are_supplied_to_the_decorated_function_more_than_once(self):
112        test_func = apply_settings(test_function)
113        settings_once = test_func(settings={'PREFER_DATES_FROM': 'past'})
114        settings_twice = test_func(settings={'PREFER_DATES_FROM': 'past'})
115        self.assertEqual(settings_once, settings_twice)
116
117    def test_apply_settings_should_return_default_settings_when_called_with_no_settings_after_once_called_with_settings_supplied_to_the_decorated_function(self):
118        test_func = apply_settings(test_function)
119        settings_once = test_func(settings={'PREFER_DATES_FROM': 'past'})
120        settings_twice = test_func()
121        self.assertNotEqual(settings_once, self.default_settings)
122        self.assertEqual(settings_twice, self.default_settings)
123
124
125class InvalidSettingsTest(BaseTestCase):
126
127    def setUp(self):
128        super(InvalidSettingsTest, self).setUp()
129
130    def test_error_is_raised_when_none_is_passed_in_settings(self):
131        test_func = apply_settings(test_function)
132        with self.assertRaisesRegexp(TypeError, 'Invalid.*None\}'):
133            test_func(settings={'PREFER_DATES_FROM': None})
134
135        with self.assertRaisesRegexp(TypeError, 'Invalid.*None\}'):
136            test_func(settings={'TIMEZONE': None})
137
138        with self.assertRaisesRegexp(TypeError, 'Invalid.*None\}'):
139            test_func(settings={'TO_TIMEZONE': None})
140
141    def test_error_is_raised_for_invalid_type_settings(self):
142        test_func = apply_settings(test_function)
143        try:
144            test_func(settings=['current_period', False, 'current'])
145        except Exception as error:
146            self.error = error
147            self.then_error_was_raised(TypeError, ["settings can only be either dict or instance of Settings class"])
148