Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import logging 

2from datetime import datetime, time, date 

3from typing import Optional, Any 

4from django.utils.translation import gettext as _ 

5from rest_framework.exceptions import ValidationError 

6import pytz 

7from django.utils.dateparse import parse_datetime as django_parse_datetime 

8from django.utils.dateparse import parse_date as django_parse_date 

9 

10logger = logging.getLogger(__name__) 

11 

12TRUE_VALUES = ( 

13 'true', 

14 '1', 

15 'yes', 

16) 

17 

18FALSE_VALUES = ( 

19 'none', 

20 'null', 

21 'false', 

22 '0', 

23 'no', 

24) 

25 

26 

27def parse_bool(v: str) -> bool: 

28 """ 

29 Parses boolean value 

30 :param v: Input string 

31 :return: bool 

32 """ 

33 s = str(v).lower() 

34 if s in TRUE_VALUES: 

35 return True 

36 if s in FALSE_VALUES: 

37 return False 

38 raise ValidationError(_("%(value)s is not one of the available choices") % {'value': v}) 

39 

40 

41def parse_datetime(v: str, tz: Any = None) -> datetime: 

42 """ 

43 Parses ISO date/datetime string to timezone-aware datetime. 

44 Supports YYYY-MM-DD date strings where time part is missing. 

45 Returns always timezone-aware datetime (assumes UTC if timezone missing). 

46 :param v: Input string to parse 

47 :param tz: Default pytz timezone or if None then use UTC as default 

48 :return: datetime with timezone 

49 """ 

50 try: 

51 t = django_parse_datetime(v) 

52 if t is None: 

53 t_date: Optional[date] = django_parse_date(v) 

54 if t_date is None: 

55 raise ValidationError(_( 

56 "“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.") % { 

57 'value': v}) 

58 t = datetime.combine(t_date, time()) 

59 if tz is None: 59 ↛ 61line 59 didn't jump to line 61, because the condition on line 59 was never false

60 tz = pytz.utc 

61 return t if t.tzinfo else tz.localize(t) 

62 except Exception: 

63 raise ValidationError(_("“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format.") % {'value': v}) 

64 

65 

66def parse_bool_or_none(v: str) -> Optional[bool]: 

67 """ 

68 Parses boolean value, or returns None if parsing fails. 

69 :param v: Input string 

70 :return: bool or None 

71 """ 

72 s = str(v).lower() 

73 if s in TRUE_VALUES: 

74 return True 

75 if s in FALSE_VALUES: 

76 return False 

77 return None 

78 

79 

80def parse_datetime_or_none(v: str, tz: Any = None) -> Optional[datetime]: 

81 """ 

82 Parses ISO date/datetime string to timezone-aware datetime. 

83 Supports YYYY-MM-DD date strings where time part is missing. 

84 Returns timezone-aware datetime (assumes UTC if timezone missing) or None if parsing fails. 

85 :param v: Input string to parse 

86 :param tz: Default pytz timezone or if None then use UTC as default 

87 :return: datetime with timezone or None 

88 """ 

89 try: 

90 t = django_parse_datetime(v) 

91 if t is None: 

92 t_date: Optional[date] = django_parse_date(v) 

93 if t_date is None: 

94 return None 

95 t = datetime.combine(t_date, time()) 

96 if tz is None: 96 ↛ 98line 96 didn't jump to line 98, because the condition on line 96 was never false

97 tz = pytz.utc 

98 return t if t.tzinfo else tz.localize(t) 

99 except Exception: 

100 return None