Projet

Général

Profil

0001-templatetags-add-date-filters-36943.patch

Valentin Deniaud, 16 janvier 2020 12:09

Télécharger (12,3 ko)

Voir les différences:

Subject: [PATCH] templatetags: add date filters (#36943)

 combo/public/templatetags/combo.py | 129 +++++++++++++++++++++++++++-
 tests/test_public_templatetags.py  | 130 +++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+), 1 deletion(-)
combo/public/templatetags/combo.py
27 27
from django.template import VariableDoesNotExist
28 28
from django.template.base import TOKEN_BLOCK, TOKEN_VAR, TOKEN_COMMENT
29 29
from django.template.defaultfilters import stringfilter
30
from django.utils import dateparse
30
from django.utils import dateparse, six
31 31
from django.utils.encoding import force_text
32 32

  
33 33
from combo.data.models import Page, Placeholder
......
269 269
@register.filter
270 270
def startswith(string, substring):
271 271
    return string and force_text(string).startswith(force_text(substring))
272

  
273
def parse_float(value):
274
    if isinstance(value, six.string_types):
275
        # replace , by . for French users comfort
276
        value = value.replace(',', '.')
277
    try:
278
        return float(value)
279
    except (ValueError, TypeError):
280
        return ''
281

  
282
def get_as_datetime(s):
283
    result = parse_datetime(s)
284
    if not result:
285
        result = parse_date(s)
286
        if result:
287
            result = datetime.datetime(year=result.year, month=result.month, day=result.day)
288
    return result
289

  
290
def make_date(date_var):
291
    '''Extract a date from a datetime, a date, a struct_time or a string'''
292
    if isinstance(date_var, datetime.datetime):
293
        return date_var.date()
294
    if isinstance(date_var, datetime.date):
295
        return date_var
296
    if isinstance(date_var, time.struct_time) or (
297
            isinstance(date_var, tuple) and len(date_var) == 9):
298
        return datetime.date(*date_var[:3])
299
    try:
300
        return get_as_datetime(date_var).date()
301
    except AttributeError:
302
        return ''
303

  
304
def make_datetime(datetime_var):
305
    '''Extract a date from a datetime, a date, a struct_time or a string'''
306
    if isinstance(datetime_var, datetime.datetime):
307
        return datetime_var
308
    if isinstance(datetime_var, datetime.date):
309
        return datetime.datetime(year=datetime_var.year, month=datetime_var.month,
310
                                 day=datetime_var.day)
311
    if isinstance(datetime_var, time.struct_time) or (
312
            isinstance(datetime_var, tuple) and len(datetime_var) == 9):
313
        return datetime.datetime(*datetime_var[:6])
314
    return get_as_datetime(datetime_var)
315

  
316
@register.filter(expects_localtime=True, is_safe=False)
317
def add_days(value, arg):
318
    value = make_date(value)  # consider only date, not hours
319
    if not value:
320
        return ''
321
    arg = parse_float(arg)
322
    if not arg:
323
        return value
324
    result = value + datetime.timedelta(days=float(arg))
325
    return result
326

  
327
@register.filter(expects_localtime=True, is_safe=False)
328
def add_hours(value, arg):
329
    value = make_datetime(value)
330
    if not value:
331
        return ''
332
    arg = parse_float(arg)
333
    if not arg:
334
        return value
335
    return value + datetime.timedelta(hours=float(arg))
336

  
337
@register.filter(expects_localtime=True, is_safe=False)
338
def age_in_days(value, today=None):
339
    value = make_date(value)
340
    if not value:
341
        return ''
342
    if today is not None:
343
        today = make_date(today)
344
        if not today:
345
            return ''
346
    else:
347
        today = datetime.date.today()
348
    return (today - value).days
349

  
350
@register.filter(expects_localtime=True, is_safe=False)
351
def age_in_hours(value, now=None):
352
    # consider value and now as datetimes (and not dates)
353
    value = make_datetime(value)
354
    if not value:
355
        return ''
356
    if now is not None:
357
        now = make_datetime(now)
358
        if not now:
359
            return ''
360
    else:
361
        now = datetime.datetime.now()
362
    return int((now - value).total_seconds() / 3600)
363

  
364
def age_in_years_and_months(born, today=None):
365
    '''Compute age since today as the number of years and months elapsed'''
366
    born = make_date(born)
367
    if not born:
368
        return ''
369
    if today is not None:
370
        today = make_date(today)
371
        if not today:
372
            return ''
373
    else:
374
        today = datetime.date.today()
375
    before = (today.month, today.day) < (born.month, born.day)
376
    years = today.year - born.year
377
    months = today.month - born.month
378
    if before:
379
        years -= 1
380
        months += 12
381
    if today.day < born.day:
382
        months -= 1
383
    return years, months
384

  
385
@register.filter(expects_localtime=True, is_safe=False)
386
def age_in_years(value, today=None):
387
    try:
388
        return age_in_years_and_months(value, today)[0]
389
    except IndexError:
390
        return ''
391

  
392
@register.filter(expects_localtime=True, is_safe=False)
393
def age_in_months(value, today=None):
394
    try:
395
        years, months = age_in_years_and_months(value, today)
396
    except ValueError:
397
        return ''
398
    return years * 12 + months
tests/test_public_templatetags.py
1
import datetime
1 2
import os
2 3
import shutil
3 4
import time
......
201 202
    assert t.render(context) == ''
202 203
    context = Context({'foo': 'bar'})
203 204
    assert t.render(context) == 'ok'
205

  
206
def test_date_maths():
207
    tmpl = Template('{{ plop|add_days:4 }}')
208
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 25, 2017'
209
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 25, 2017'
210
    tmpl = Template('{{ plop|add_days:"-1" }}')
211
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 20, 2017'
212
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 20, 2017'
213
    tmpl = Template('{{ plop|add_days:1.5 }}')
214
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 22, 2017'
215
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 22, 2017'
216
    tmpl = Template('{{ plop|add_days:"1.5" }}')
217
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 22, 2017'
218
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 22, 2017'
219

  
220
    tmpl = Template('{{ plop|add_hours:24 }}')
221
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 22, 2017, midnight'
222
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 22, 2017, 6 p.m.'
223
    tmpl = Template('{{ plop|add_hours:"12.5" }}')
224
    assert tmpl.render(Context({'plop': '2017-12-21'})) == 'Dec. 21, 2017, 12:30 p.m.'
225
    assert tmpl.render(Context({'plop': '2017-12-21 18:00'})) == 'Dec. 22, 2017, 6:30 a.m.'
226

  
227
def test_age_in():
228
    context = {
229
        'form_var_datefield': time.strptime('2018-07-31', '%Y-%m-%d'),
230
        'form_var_datefield2': time.strptime('2018-08-31', '%Y-%m-%d'),
231
        'form_var_datestring': '2018-07-31',
232
        'today': datetime.date.today(),
233
        'now': datetime.datetime.now(),
234
    }
235
    for condition_value in (  # hope date is > 2018
236
            # age_in_days
237
            '"1970-01-01"|age_in_days > 0',
238
            '"2500-01-01"|age_in_days < 0',
239
            'form_var_datefield|age_in_days > 50',
240
            'form_var_datefield|age_in_days:form_var_datestring == 0',
241
            'form_var_datefield|age_in_days:form_var_datefield2 == 31',
242
            'form_var_datefield2|age_in_days:form_var_datefield == -31',
243
            'form_var_datefield|age_in_days:form_var_datefield == 0',
244
            'form_var_datestring|age_in_days:form_var_datefield == 0',
245
            'form_var_datestring|age_in_days:form_var_datestring == 0',
246
            'today|add_days:-5|age_in_days == 5',
247
            'today|add_days:5|age_in_days == -5',
248
            'today|age_in_days == 0',
249
            # with datetimes
250
            '"1970-01-01 02:03"|age_in_days > 0',
251
            '"2500-01-01 02:03"|age_in_days < 0',
252
            'now|age_in_days == 0',
253
            'now|add_hours:-24|age_in_days == 1',
254
            'now|add_hours:24|age_in_days == -1',
255
            '"2010-11-12 13:14"|age_in_days:"2010-11-12 13:14" == 0',
256
            '"2010-11-12 13:14"|age_in_days:"2010-11-12 12:14" == 0',
257
            '"2010-11-12 13:14"|age_in_days:"2010-11-12 14:14" == 0',
258
            '"2010-11-12 13:14"|age_in_days:"2010-11-13 13:13" == 1',
259
            '"2010-11-12 13:14"|age_in_days:"2010-11-13 13:15" == 1',
260

  
261
            # age_in_hours
262
            'now|add_hours:-5|age_in_hours == 5',
263
            'now|add_hours:25|age_in_hours == -24',
264
            'now|age_in_hours == 0',
265
            '"2010-11-12 13:14"|age_in_hours:"2010-11-12 13:14" == 0',
266
            '"2010-11-12 13:14"|age_in_hours:"2010-11-12 12:14" == -1',
267
            '"2010-11-12 13:14"|age_in_hours:"2010-11-12 14:14" == 1',
268
            '"2010-11-12 13:14"|age_in_hours:"2010-11-13 13:13" == 23',
269
            '"2010-11-12 13:14"|age_in_hours:"2010-11-13 13:15" == 24',
270
            '"1970-01-01 02:03"|age_in_hours > 0',
271
            '"2500-01-01 02:03"|age_in_hours < 0',
272
            # with dates
273
            '"1970-01-01"|age_in_hours > 0',
274
            '"2500-01-01"|age_in_hours < 0',
275
            'form_var_datefield|age_in_hours > 1200',
276
            'form_var_datefield|age_in_hours:form_var_datestring == 0',
277
            'form_var_datefield|age_in_hours:form_var_datefield2 == 744',  # 31*24
278
            'form_var_datefield2|age_in_hours:form_var_datefield == -744',
279
            'form_var_datefield|age_in_hours:form_var_datefield == 0',
280
            'form_var_datestring|age_in_hours:form_var_datefield == 0',
281
            'form_var_datestring|age_in_hours:form_var_datestring == 0',
282
            'today|add_days:-1|age_in_hours >= 24',
283
            'today|add_days:1|age_in_hours <= -0',
284
            'today|add_days:1|age_in_hours >= -24',
285
            'today|age_in_hours >= 0',
286

  
287
            # age_in_years
288
            '"1970-01-01"|age_in_years > 0',
289
            '"2500-01-01"|age_in_years < 0',
290
            'form_var_datefield|age_in_years:"2019-07-31" == 1',
291
            'form_var_datefield|age_in_years:"2019-09-20" == 1',
292
            'form_var_datefield|age_in_years:"2020-07-30" == 1',
293
            'form_var_datefield|age_in_years:"2020-07-31" == 2',
294
            'form_var_datestring|age_in_years:"2019-07-31" == 1',
295
            'today|age_in_years == 0',
296
            'today|add_days:-500|age_in_years == 1',
297
            'today|add_days:-300|age_in_years == 0',
298
            'today|add_days:300|age_in_years == -1',
299
            'now|age_in_years == 0',
300
            'now|add_days:-500|age_in_years == 1',
301
            'now|add_days:-300|age_in_years == 0',
302
            'now|add_days:300|age_in_years == -1',
303
            '"1970-01-01 02:03"|age_in_years > 0',
304
            '"2500-01-01 02:03"|age_in_years < 0',
305

  
306
            # age_in_months
307
            'form_var_datefield|age_in_months:form_var_datefield2 == 1',
308
            'form_var_datefield2|age_in_months:form_var_datefield == -1',
309
            'form_var_datefield|age_in_months:"2019-07-31" == 12',
310
            'form_var_datefield|age_in_months:"2019-08-20" == 12',
311
            'form_var_datefield|age_in_months:"2019-09-20" == 13',
312
            'form_var_datestring|age_in_months:"2019-09-20" == 13',
313
            '"1970-01-01"|age_in_months > 0',
314
            '"2500-01-01"|age_in_months < 0',
315
            '"1970-01-01 02:03"|age_in_months > 0',
316
            '"2500-01-01 02:03"|age_in_months < 0',
317

  
318
            # fail produce empty string
319
            'foobar|age_in_days == ""',
320
            '"foobar"|age_in_days == ""',
321
            '"1970-01-01"|age_in_days:"foobar" == ""',
322
            'foobar|age_in_hours == ""',
323
            '"foobar"|age_in_hours == ""',
324
            '"1970-01-01"|age_in_hours:"foobar" == ""',
325
            'foobar|age_in_years == ""',
326
            '"foobar"|age_in_years == ""',
327
            '"1970-01-01"|age_in_years:"foobar" == ""',
328
            'foobar|age_in_months == ""',
329
            '"foobar"|age_in_months == ""',
330
            '"1970-01-01"|age_in_months:"foobar" == ""',
331
            ):
332
        tmpl = Template('{%% if %s %%}Good{%% endif %%}' % condition_value)
333
        assert tmpl.render(Context(context)) == 'Good'
204
-