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.core.exceptions import ValidationError 

5from django.utils.translation import gettext as _ 

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 _( 

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

58 ) 

59 % {"value": v} 

60 ) 

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

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

63 tz = pytz.utc 

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

65 except Exception: 

66 raise ValidationError( 

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

68 % {"value": v} 

69 ) 

70 

71 

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

73 """ 

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

75 :param v: Input string 

76 :return: bool or None 

77 """ 

78 s = str(v).lower() 

79 if s in TRUE_VALUES: 

80 return True 

81 if s in FALSE_VALUES: 

82 return False 

83 return None 

84 

85 

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

87 """ 

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

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

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

91 :param v: Input string to parse 

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

93 :return: datetime with timezone or None 

94 """ 

95 try: 

96 t = django_parse_datetime(v) 

97 if t is None: 

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

99 if t_date is None: 

100 return None 

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

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

103 tz = pytz.utc 

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

105 except Exception: 

106 return None