1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
Date Display
============
We aim for "friendly" display of dates. That means we prefer to express the
date "relative to the present" when it is close to now. Instead of saying
"2007-12-15 06:15 EST" we say "3 minutes ago" or "in 18 seconds".
There are two TALES formatters:
o fmt:approximatedate does the hard work of turning a timestamp into an
relative time description. It should be used for tabular data. For
example:
Product Registered Registrant
======= ========== ==========
foobar *3 minutes ago* James Wilson
bzrness *2005-11-07* Richard Downes
o fmt:displaydate is similar but is better in paragraphs or sentences. So,
for example: "FooBar was registered *on 2005-11-06* and last updated
*4 minutes ago*."
The difference between them is TINY: fmt:displaydate prepends "on " to the
result of fmt:approximatedate IF the time delta is greater than 1 day, and
hence if the display will be the date.
First, let's bring in some dependencies:
>>> from datetime import datetime, timedelta
>>> from lp.testing import test_tales
>>> import pytz
>>> UTC = pytz.timezone('UTC')
fmt:approximatedate and fmt:displaydate display the difference between
the formatted timestamp and the present. This is a really bad idea
for tests, so we register an alternate formatter that use the same
formatting code, but always display the difference from a known
timestamp.
>>> fixed_time_utc = datetime(2005, 12, 25, 12, 0, 0, tzinfo=UTC)
>>> fixed_time = datetime(2005, 12, 25, 12, 0, 0)
>>> from lp.app.browser.tales import DateTimeFormatterAPI
>>> class TestDateTimeFormatterAPI(DateTimeFormatterAPI):
... def _now(self):
... if self._datetime.tzinfo:
... return fixed_time_utc
... else:
... return fixed_time
>>> from zope.app.testing import ztapi
>>> from zope.traversing.interfaces import IPathAdapter
>>> ztapi.provideAdapter(
... datetime, IPathAdapter, TestDateTimeFormatterAPI, 'testfmt')
A time that is ten seconds or less will be displayed as an approximate:
>>> t = fixed_time + timedelta(0, 5, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'in a moment'
>>> t = fixed_time + timedelta(0, 9, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'in a moment'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
>>> t = fixed_time_utc - timedelta(0, 10, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'a moment ago'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
A time that is very close to the present will be displayed in seconds:
>>> t = fixed_time + timedelta(0, 11, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'in 11 seconds'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
>>> t = fixed_time_utc - timedelta(0, 25, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'25 seconds ago'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
Further out we expect minutes. Note that for singular units (e.g. "1
minute"), we present the singular unit:
>>> t = fixed_time_utc + timedelta(0, 185, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'in 3 minutes'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
>>> t = fixed_time_utc - timedelta(0, 75, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'1 minute ago'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
Further out we expect hours:
>>> t = fixed_time_utc + timedelta(0, 3635, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'in 1 hour'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
>>> t = fixed_time_utc - timedelta(0, 3635, 0)
>>> test_tales('t/testfmt:approximatedate', t=t)
'1 hour ago'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
True
And if the approximate date is more than a day away, we expect the date. We
also expect the fmt:displaydate to change form, and become "on yyyy-mm-dd".
>>> t = datetime(2004, 1, 13, 15, 35)
>>> test_tales('t/testfmt:approximatedate', t=t)
'2004-01-13'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
False
>>> test_tales('t/testfmt:displaydate', t=t)
'on 2004-01-13'
>>> t = datetime(2015, 1, 13, 15, 35)
>>> test_tales('t/testfmt:approximatedate', t=t)
'2015-01-13'
>>> print (test_tales('t/testfmt:approximatedate', t=t) ==
... test_tales('t/testfmt:displaydate', t=t))
False
>>> test_tales('t/testfmt:displaydate', t=t)
'on 2015-01-13'
|