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

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) 2025, Brandon Nielsen 

4# All rights reserved. 

5# 

6# This software may be modified and distributed under the terms 

7# of the BSD license. See the LICENSE file for details. 

8 

9from aniso8601.builders import TupleBuilder 

10from aniso8601.builders.python import PythonTimeBuilder 

11from aniso8601.compat import is_string 

12from aniso8601.exceptions import ISOFormatError 

13from aniso8601.resolution import DateResolution 

14 

15 

16def get_date_resolution(isodatestr): 

17 # Valid string formats are: 

18 # 

19 # Y[YYY] 

20 # YYYY-MM-DD 

21 # YYYYMMDD 

22 # YYYY-MM 

23 # YYYY-Www 

24 # YYYYWww 

25 # YYYY-Www-D 

26 # YYYYWwwD 

27 # YYYY-DDD 

28 # YYYYDDD 

29 isodatetuple = parse_date(isodatestr, builder=TupleBuilder) 

30 

31 if isodatetuple.DDD is not None: 

32 # YYYY-DDD 

33 # YYYYDDD 

34 return DateResolution.Ordinal 

35 

36 if isodatetuple.D is not None: 

37 # YYYY-Www-D 

38 # YYYYWwwD 

39 return DateResolution.Weekday 

40 

41 if isodatetuple.Www is not None: 

42 # YYYY-Www 

43 # YYYYWww 

44 return DateResolution.Week 

45 

46 if isodatetuple.DD is not None: 

47 # YYYY-MM-DD 

48 # YYYYMMDD 

49 return DateResolution.Day 

50 

51 if isodatetuple.MM is not None: 

52 # YYYY-MM 

53 return DateResolution.Month 

54 

55 # Y[YYY] 

56 return DateResolution.Year 

57 

58 

59def parse_date(isodatestr, builder=PythonTimeBuilder): 

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

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

62 # 

63 # YY 

64 # YYYY 

65 # YYYY-MM-DD 

66 # YYYYMMDD 

67 # YYYY-MM 

68 # YYYY-Www 

69 # YYYYWww 

70 # YYYY-Www-D 

71 # YYYYWwwD 

72 # YYYY-DDD 

73 # YYYYDDD 

74 if is_string(isodatestr) is False: 

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

76 

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

78 raise NotImplementedError( 

79 "ISO 8601 extended year representation not supported." 

80 ) 

81 

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

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

84 

85 yearstr = None 

86 monthstr = None 

87 daystr = None 

88 weekstr = None 

89 weekdaystr = None 

90 ordinaldaystr = None 

91 

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

93 # YY 

94 # YYYY 

95 yearstr = isodatestr 

96 elif "W" in isodatestr: 

97 if len(isodatestr) == 10: 

98 # YYYY-Www-D 

99 yearstr = isodatestr[0:4] 

100 weekstr = isodatestr[6:8] 

101 weekdaystr = isodatestr[9] 

102 elif len(isodatestr) == 8: 

103 if "-" in isodatestr: 

104 # YYYY-Www 

105 yearstr = isodatestr[0:4] 

106 weekstr = isodatestr[6:] 

107 else: 

108 # YYYYWwwD 

109 yearstr = isodatestr[0:4] 

110 weekstr = isodatestr[5:7] 

111 weekdaystr = isodatestr[7] 

112 elif len(isodatestr) == 7: 

113 # YYYYWww 

114 yearstr = isodatestr[0:4] 

115 weekstr = isodatestr[5:] 

116 elif len(isodatestr) == 7: 

117 if "-" in isodatestr: 

118 # YYYY-MM 

119 yearstr = isodatestr[0:4] 

120 monthstr = isodatestr[5:] 

121 else: 

122 # YYYYDDD 

123 yearstr = isodatestr[0:4] 

124 ordinaldaystr = isodatestr[4:] 

125 elif len(isodatestr) == 8: 

126 if "-" in isodatestr: 

127 # YYYY-DDD 

128 yearstr = isodatestr[0:4] 

129 ordinaldaystr = isodatestr[5:] 

130 else: 

131 # YYYYMMDD 

132 yearstr = isodatestr[0:4] 

133 monthstr = isodatestr[4:6] 

134 daystr = isodatestr[6:] 

135 elif len(isodatestr) == 10: 

136 # YYYY-MM-DD 

137 yearstr = isodatestr[0:4] 

138 monthstr = isodatestr[5:7] 

139 daystr = isodatestr[8:] 

140 else: 

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

142 

143 hascomponent = False 

144 

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

146 if componentstr is not None: 

147 hascomponent = True 

148 

149 if componentstr.isdigit() is False: 

150 raise ISOFormatError( 

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

152 ) 

153 

154 if hascomponent is False: 

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

156 

157 return builder.build_date( 

158 YYYY=yearstr, 

159 MM=monthstr, 

160 DD=daystr, 

161 Www=weekstr, 

162 D=weekdaystr, 

163 DDD=ordinaldaystr, 

164 )