Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/aniso8601/date.py: 82%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

76 statements  

1# -*- coding: utf-8 -*- 

2 

3# Copyright (c) 2026, Brandon Nielsen 

4# SPDX-License-Identifier: BSD-3-Clause 

5 

6from aniso8601.builders import TupleBuilder 

7from aniso8601.builders.python import PythonTimeBuilder 

8from aniso8601.compat import is_string 

9from aniso8601.exceptions import ISOFormatError 

10from aniso8601.resolution import DateResolution 

11 

12 

13def get_date_resolution(isodatestr): 

14 # Valid string formats are: 

15 # 

16 # Y[YYY] 

17 # YYYY-MM-DD 

18 # YYYYMMDD 

19 # YYYY-MM 

20 # YYYY-Www 

21 # YYYYWww 

22 # YYYY-Www-D 

23 # YYYYWwwD 

24 # YYYY-DDD 

25 # YYYYDDD 

26 isodatetuple = parse_date(isodatestr, builder=TupleBuilder) 

27 

28 if isodatetuple.DDD is not None: 

29 # YYYY-DDD 

30 # YYYYDDD 

31 return DateResolution.Ordinal 

32 

33 if isodatetuple.D is not None: 

34 # YYYY-Www-D 

35 # YYYYWwwD 

36 return DateResolution.Weekday 

37 

38 if isodatetuple.Www is not None: 

39 # YYYY-Www 

40 # YYYYWww 

41 return DateResolution.Week 

42 

43 if isodatetuple.DD is not None: 

44 # YYYY-MM-DD 

45 # YYYYMMDD 

46 return DateResolution.Day 

47 

48 if isodatetuple.MM is not None: 

49 # YYYY-MM 

50 return DateResolution.Month 

51 

52 # Y[YYY] 

53 return DateResolution.Year 

54 

55 

56def parse_date(isodatestr, builder=PythonTimeBuilder): 

57 # Given a string in any ISO 8601 date format, return a datetime.date 

58 # object that corresponds to the given date. Valid string formats are: 

59 # 

60 # YY 

61 # YYYY 

62 # YYYY-MM-DD 

63 # YYYYMMDD 

64 # YYYY-MM 

65 # YYYY-Www 

66 # YYYYWww 

67 # YYYY-Www-D 

68 # YYYYWwwD 

69 # YYYY-DDD 

70 # YYYYDDD 

71 if is_string(isodatestr) is False: 

72 raise ValueError("Date must be string.") 

73 

74 if isodatestr.startswith("+") or isodatestr.startswith("-"): 

75 raise NotImplementedError( 

76 "ISO 8601 extended year representation not supported." 

77 ) 

78 

79 if len(isodatestr) == 0 or isodatestr.count("-") > 2: 

80 raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr)) 

81 

82 yearstr = None 

83 monthstr = None 

84 daystr = None 

85 weekstr = None 

86 weekdaystr = None 

87 ordinaldaystr = None 

88 

89 if len(isodatestr) in (2, 4): 

90 # YY 

91 # YYYY 

92 yearstr = isodatestr 

93 elif "W" in isodatestr: 

94 if len(isodatestr) == 10: 

95 # YYYY-Www-D 

96 yearstr = isodatestr[0:4] 

97 weekstr = isodatestr[6:8] 

98 weekdaystr = isodatestr[9] 

99 elif len(isodatestr) == 8: 

100 if "-" in isodatestr: 

101 # YYYY-Www 

102 yearstr = isodatestr[0:4] 

103 weekstr = isodatestr[6:] 

104 else: 

105 # YYYYWwwD 

106 yearstr = isodatestr[0:4] 

107 weekstr = isodatestr[5:7] 

108 weekdaystr = isodatestr[7] 

109 elif len(isodatestr) == 7: 

110 # YYYYWww 

111 yearstr = isodatestr[0:4] 

112 weekstr = isodatestr[5:] 

113 elif len(isodatestr) == 7: 

114 if "-" in isodatestr: 

115 # YYYY-MM 

116 yearstr = isodatestr[0:4] 

117 monthstr = isodatestr[5:] 

118 else: 

119 # YYYYDDD 

120 yearstr = isodatestr[0:4] 

121 ordinaldaystr = isodatestr[4:] 

122 elif len(isodatestr) == 8: 

123 if "-" in isodatestr: 

124 # YYYY-DDD 

125 yearstr = isodatestr[0:4] 

126 ordinaldaystr = isodatestr[5:] 

127 else: 

128 # YYYYMMDD 

129 yearstr = isodatestr[0:4] 

130 monthstr = isodatestr[4:6] 

131 daystr = isodatestr[6:] 

132 elif len(isodatestr) == 10: 

133 # YYYY-MM-DD 

134 yearstr = isodatestr[0:4] 

135 monthstr = isodatestr[5:7] 

136 daystr = isodatestr[8:] 

137 else: 

138 raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr)) 

139 

140 hascomponent = False 

141 

142 for componentstr in [yearstr, monthstr, daystr, weekstr, weekdaystr, ordinaldaystr]: 

143 if componentstr is not None: 

144 hascomponent = True 

145 

146 if componentstr.isdigit() is False: 

147 raise ISOFormatError( 

148 '"{0}" is not a valid ISO 8601 date.'.format(isodatestr) 

149 ) 

150 

151 if hascomponent is False: 

152 raise ISOFormatError('"{0}" is not a valid ISO 8601 date.'.format(isodatestr)) 

153 

154 return builder.build_date( 

155 YYYY=yearstr, 

156 MM=monthstr, 

157 DD=daystr, 

158 Www=weekstr, 

159 D=weekdaystr, 

160 DDD=ordinaldaystr, 

161 )