Passed
Push — master ( 05ccdf...015759 )
by Fabio
01:12
created

benedict.dicts.parse.parse_util.parse_date()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nop 2
1
# -*- coding: utf-8 -*-
2
3
from benedict.serializers import JSONSerializer
4
from benedict.utils import type_util
5
6
from datetime import datetime
7
from dateutil import parser as date_parser
8
from decimal import Decimal, DecimalException
9
from MailChecker import MailChecker
10
from phonenumbers import phonenumberutil, PhoneNumberFormat
11
from six import text_type
12
from slugify import slugify
13
14
import ftfy
15
import phonenumbers
16
import re
17
18
19
def _parse_with(val, type_checker, parser, **kwargs):
20
    if val is None:
21
        return None
22
    if callable(type_checker) and type_checker(val):
23
        return val
24
    s = text_type(val)
25
    if not len(s):
26
        return None
27
    return parser(s, **kwargs)
28
29
30
def _parse_bool(val):
31
    val = val.lower()
32
    if val in ['1', 'true', 'yes', 'ok', 'on']:
33
        return True
34
    elif val in ['0', 'false', 'no', 'ko', 'off']:
35
        return False
36
    return None
37
38
39
def parse_bool(val):
40
    return _parse_with(val, type_util.is_bool, _parse_bool)
41
42
43
def parse_date(val, format=None):
44
    val = parse_datetime(val, format)
45
    if val:
46
        return val.date()
47
    return None
48
49
50
def _parse_datetime_with_format(val, format):
51
    try:
52
        return datetime.strptime(val, format)
53
    except Exception:
54
        return None
55
56
57
def _parse_datetime_without_format(val):
58
    try:
59
        return date_parser.parse(val)
60
    except Exception:
61
        return _parse_datetime_from_timestamp(val)
62
63
64
def _parse_datetime_from_timestamp(val):
65
    try:
66
        return datetime.fromtimestamp(float(val))
67
    except Exception:
68
        return None
69
70
71
def parse_datetime(val, format=None):
72
    if type_util.is_datetime(val):
73
        return val
74
    s = text_type(val)
75
    if format:
76
        return _parse_datetime_with_format(s, format)
77
    else:
78
        return _parse_datetime_without_format(s)
79
80
81
def _parse_decimal(val):
82
    try:
83
        return Decimal(val)
84
    except (ValueError, DecimalException):
85
        return None
86
87
88
def parse_decimal(val):
89
    return _parse_with(val, type_util.is_decimal, _parse_decimal)
90
91
92
def _parse_dict(val):
93
    serializer = JSONSerializer()
94
    try:
95
        d = serializer.decode(val)
96
        if type_util.is_dict(d):
97
            return d
98
        return None
99
    except Exception:
100
        return None
101
102
103
def parse_dict(val):
104
    return _parse_with(val, type_util.is_dict, _parse_dict)
105
106
107
def _parse_float(val):
108
    try:
109
        return float(val)
110
    except ValueError:
111
        return None
112
113
114
def parse_float(val):
115
    return _parse_with(val, type_util.is_float, _parse_float)
116
117
118
def _parse_email(val, check_blacklist=True):
119
    val = val.lower()
120
    if check_blacklist:
121
        if not MailChecker.is_valid(val):
122
            return None
123
    else:
124
        if not MailChecker.is_valid_email_format(val):
125
            return None
126
    return val
127
128
129
def parse_email(val, check_blacklist=True):
130
    return _parse_with(
131
        val, None, _parse_email, check_blacklist=check_blacklist)
132
133
134
def _parse_int(val):
135
    try:
136
        return int(val)
137
    except ValueError:
138
        return None
139
140
141
def parse_int(val):
142
    return _parse_with(val, type_util.is_integer, _parse_int)
143
144
145
def _parse_list(val, separator=None):
146
    serializer = JSONSerializer()
147
    try:
148
        l = serializer.decode(val)
149
        if type_util.is_list(l):
150
            return l
151
    except Exception:
152
        if separator:
153
            l = list(val.split(separator))
154
            return l
155
    return None
156
157
158
def parse_list(val, separator=None):
159
    val = _parse_with(val, type_util.is_list_or_tuple,
160
                      _parse_list, separator=separator)
161
    return list(val) if type_util.is_list_or_tuple(val) else val
162
163
164
def _parse_phonenumber(val, country_code=None):
165
    try:
166
        phone_obj = phonenumbers.parse(val, country_code)
167
        if phonenumbers.is_valid_number(phone_obj):
168
            return {
169
                'e164': phonenumbers.format_number(
170
                    phone_obj, PhoneNumberFormat.E164),
171
                'international': phonenumbers.format_number(
172
                    phone_obj, PhoneNumberFormat.INTERNATIONAL),
173
                'national': phonenumbers.format_number(
174
                    phone_obj, PhoneNumberFormat.NATIONAL),
175
            }
176
        return None
177
    except phonenumberutil.NumberParseException:
178
        return None
179
180
181
def parse_phonenumber(val, country_code=None):
182
    s = parse_str(val)
183
    if not s:
184
        return None
185
    phone_raw = re.sub(r'[^0-9\+]', ' ', s)
186
    phone_raw = phone_raw.strip()
187
    if phone_raw.startswith('00'):
188
        phone_raw = '+{}'.format(phone_raw[2:])
189
    if country_code and len(country_code) >= 2:
190
        country_code = country_code[0:2].upper()
191
    return _parse_with(
192
        phone_raw, None, _parse_phonenumber, country_code=country_code)
193
194
195
def _parse_slug(val):
196
    return slugify(val)
197
198
199
def parse_slug(val):
200
    s = parse_str(val)
201
    return _parse_slug(s)
202
203
204
def parse_str(val):
205
    if type_util.is_string(val):
206
        try:
207
            val = ftfy.fix_text(val)
208
        except UnicodeError:
209
            pass
210
    else:
211
        val = text_type(val)
212
    val = val.strip()
213
    val = ' '.join(val.split())
214
    return val
215
216
217
def parse_uuid(val):
218
    s = parse_str(val)
219
    return s if type_util.is_uuid(s) else None
220