Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/templatetags/tz.py: 33%

102 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from datetime import datetime, tzinfo 

2 

3try: 

4 import zoneinfo 

5except ImportError: 

6 from backports import zoneinfo 

7 

8from django.conf import settings 

9from django.template import Library, Node, TemplateSyntaxError 

10from django.utils import timezone 

11 

12register = Library() 

13 

14 

15# RemovedInDjango50Warning: shim to allow catching the exception in the calling 

16# scope if pytz is not installed. 

17class UnknownTimezoneException(BaseException): 

18 pass 

19 

20 

21# RemovedInDjango50Warning 

22def timezone_constructor(tzname): 

23 if settings.USE_DEPRECATED_PYTZ: 

24 import pytz 

25 

26 try: 

27 return pytz.timezone(tzname) 

28 except pytz.UnknownTimeZoneError: 

29 raise UnknownTimezoneException 

30 try: 

31 return zoneinfo.ZoneInfo(tzname) 

32 except zoneinfo.ZoneInfoNotFoundError: 

33 raise UnknownTimezoneException 

34 

35 

36# HACK: datetime instances cannot be assigned new attributes. Define a subclass 

37# in order to define new attributes in do_timezone(). 

38class datetimeobject(datetime): 

39 pass 

40 

41 

42# Template filters 

43 

44 

45@register.filter 

46def localtime(value): 

47 """ 

48 Convert a datetime to local time in the active time zone. 

49 

50 This only makes sense within a {% localtime off %} block. 

51 """ 

52 return do_timezone(value, timezone.get_current_timezone()) 

53 

54 

55@register.filter 

56def utc(value): 

57 """ 

58 Convert a datetime to UTC. 

59 """ 

60 return do_timezone(value, timezone.utc) 

61 

62 

63@register.filter("timezone") 

64def do_timezone(value, arg): 

65 """ 

66 Convert a datetime to local time in a given time zone. 

67 

68 The argument must be an instance of a tzinfo subclass or a time zone name. 

69 

70 Naive datetimes are assumed to be in local time in the default time zone. 

71 """ 

72 if not isinstance(value, datetime): 

73 return "" 

74 

75 # Obtain a timezone-aware datetime 

76 try: 

77 if timezone.is_naive(value): 

78 default_timezone = timezone.get_default_timezone() 

79 value = timezone.make_aware(value, default_timezone) 

80 # Filters must never raise exceptions, and pytz' exceptions inherit 

81 # Exception directly, not a specific subclass. So catch everything. 

82 except Exception: 

83 return "" 

84 

85 # Obtain a tzinfo instance 

86 if isinstance(arg, tzinfo): 

87 tz = arg 

88 elif isinstance(arg, str): 

89 try: 

90 tz = timezone_constructor(arg) 

91 except UnknownTimezoneException: 

92 return "" 

93 else: 

94 return "" 

95 

96 result = timezone.localtime(value, tz) 

97 

98 # HACK: the convert_to_local_time flag will prevent 

99 # automatic conversion of the value to local time. 

100 result = datetimeobject( 

101 result.year, 

102 result.month, 

103 result.day, 

104 result.hour, 

105 result.minute, 

106 result.second, 

107 result.microsecond, 

108 result.tzinfo, 

109 ) 

110 result.convert_to_local_time = False 

111 return result 

112 

113 

114# Template tags 

115 

116 

117class LocalTimeNode(Node): 

118 """ 

119 Template node class used by ``localtime_tag``. 

120 """ 

121 

122 def __init__(self, nodelist, use_tz): 

123 self.nodelist = nodelist 

124 self.use_tz = use_tz 

125 

126 def render(self, context): 

127 old_setting = context.use_tz 

128 context.use_tz = self.use_tz 

129 output = self.nodelist.render(context) 

130 context.use_tz = old_setting 

131 return output 

132 

133 

134class TimezoneNode(Node): 

135 """ 

136 Template node class used by ``timezone_tag``. 

137 """ 

138 

139 def __init__(self, nodelist, tz): 

140 self.nodelist = nodelist 

141 self.tz = tz 

142 

143 def render(self, context): 

144 with timezone.override(self.tz.resolve(context)): 

145 output = self.nodelist.render(context) 

146 return output 

147 

148 

149class GetCurrentTimezoneNode(Node): 

150 """ 

151 Template node class used by ``get_current_timezone_tag``. 

152 """ 

153 

154 def __init__(self, variable): 

155 self.variable = variable 

156 

157 def render(self, context): 

158 context[self.variable] = timezone.get_current_timezone_name() 

159 return "" 

160 

161 

162@register.tag("localtime") 

163def localtime_tag(parser, token): 

164 """ 

165 Force or prevent conversion of datetime objects to local time, 

166 regardless of the value of ``settings.USE_TZ``. 

167 

168 Sample usage:: 

169 

170 {% localtime off %}{{ value_in_utc }}{% endlocaltime %} 

171 """ 

172 bits = token.split_contents() 

173 if len(bits) == 1: 

174 use_tz = True 

175 elif len(bits) > 2 or bits[1] not in ("on", "off"): 

176 raise TemplateSyntaxError("%r argument should be 'on' or 'off'" % bits[0]) 

177 else: 

178 use_tz = bits[1] == "on" 

179 nodelist = parser.parse(("endlocaltime",)) 

180 parser.delete_first_token() 

181 return LocalTimeNode(nodelist, use_tz) 

182 

183 

184@register.tag("timezone") 

185def timezone_tag(parser, token): 

186 """ 

187 Enable a given time zone just for this block. 

188 

189 The ``timezone`` argument must be an instance of a ``tzinfo`` subclass, a 

190 time zone name, or ``None``. If it is ``None``, the default time zone is 

191 used within the block. 

192 

193 Sample usage:: 

194 

195 {% timezone "Europe/Paris" %} 

196 It is {{ now }} in Paris. 

197 {% endtimezone %} 

198 """ 

199 bits = token.split_contents() 

200 if len(bits) != 2: 

201 raise TemplateSyntaxError("'%s' takes one argument (timezone)" % bits[0]) 

202 tz = parser.compile_filter(bits[1]) 

203 nodelist = parser.parse(("endtimezone",)) 

204 parser.delete_first_token() 

205 return TimezoneNode(nodelist, tz) 

206 

207 

208@register.tag("get_current_timezone") 

209def get_current_timezone_tag(parser, token): 

210 """ 

211 Store the name of the current time zone in the context. 

212 

213 Usage:: 

214 

215 {% get_current_timezone as TIME_ZONE %} 

216 

217 This will fetch the currently active time zone and put its name 

218 into the ``TIME_ZONE`` context variable. 

219 """ 

220 # token.split_contents() isn't useful here because this tag doesn't accept 

221 # variable as arguments. 

222 args = token.contents.split() 

223 if len(args) != 3 or args[1] != "as": 

224 raise TemplateSyntaxError( 

225 "'get_current_timezone' requires 'as variable' (got %r)" % args 

226 ) 

227 return GetCurrentTimezoneNode(args[2])