27 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config |
25 from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config |
28 from pyams_utils.interfaces.tales import ITALESExtension |
26 from pyams_utils.interfaces.tales import ITALESExtension |
29 from pyams_utils.request import check_request |
27 from pyams_utils.request import check_request |
30 from pyams_utils.timezone import gmtime, tztime |
28 from pyams_utils.timezone import gmtime, tztime |
31 |
29 |
|
30 |
|
31 __docformat__ = 'restructuredtext' |
|
32 |
32 from pyams_utils import _ |
33 from pyams_utils import _ |
33 |
34 |
34 |
35 |
35 def unidate(value): |
36 def unidate(value): |
36 """Get specified date converted to unicode ISO format |
37 """Get specified date converted to unicode ISO format |
37 |
38 |
38 Dates are always assumed to be stored in GMT timezone |
39 Dates are always assumed to be stored in GMT timezone |
39 |
40 |
40 :param date value: input date to convert to unicode |
41 :param date value: input date to convert to unicode |
41 :return: unicode; input date converted to unicode |
42 :return: unicode; input date converted to unicode |
42 |
43 |
43 >>> from datetime import datetime |
44 >>> from datetime import datetime |
44 >>> from pyams_utils.date import unidate |
45 >>> from pyams_utils.date import unidate |
98 |
99 |
99 EXT_DATE_FORMAT = _("on %d/%m/%Y") |
100 EXT_DATE_FORMAT = _("on %d/%m/%Y") |
100 EXT_DATETIME_FORMAT = _("on %d/%m/%Y at %H:%M") |
101 EXT_DATETIME_FORMAT = _("on %d/%m/%Y at %H:%M") |
101 |
102 |
102 |
103 |
103 def format_date(value, format=EXT_DATE_FORMAT, request=None): |
104 def format_date(value, format_string=EXT_DATE_FORMAT, request=None): |
104 """Format given date with the given format |
105 """Format given date with the given format |
105 |
106 |
106 :param datetime value: the value to format |
107 :param datetime value: the value to format |
107 :param str format: a format string to use by `strftime` function |
108 :param str format_string: a format string to use by `strftime` function |
108 :param request: the request from which to extract localization info for translation |
109 :param request: the request from which to extract localization info for translation |
109 :return: str; input datetime converted to given format |
110 :return: str; input datetime converted to given format |
110 |
111 |
111 >>> from datetime import datetime |
112 >>> from datetime import datetime |
112 >>> from pyams_utils.date import format_date, SH_DATE_FORMAT |
113 >>> from pyams_utils.date import format_date, SH_DATE_FORMAT |
119 if not value: |
120 if not value: |
120 return '--' |
121 return '--' |
121 if request is None: |
122 if request is None: |
122 request = check_request() |
123 request = check_request() |
123 localizer = request.localizer |
124 localizer = request.localizer |
124 return datetime.strftime(tztime(value), localizer.translate(format)) |
125 return datetime.strftime(tztime(value), localizer.translate(format_string)) |
125 |
126 |
126 |
127 |
127 def format_datetime(value, format=EXT_DATETIME_FORMAT, request=None): |
128 def format_datetime(value, format_string=EXT_DATETIME_FORMAT, request=None): |
128 """Format given datetime with the given format including time |
129 """Format given datetime with the given format including time |
129 |
130 |
130 :param datetime value: the value to format |
131 :param datetime value: the value to format |
131 :param str format: a format string to use by `strftime` function |
132 :param str format_string: a format string to use by `strftime` function |
132 :param request: request; the request from which to extract localization info for translation |
133 :param request: request; the request from which to extract localization info for translation |
133 :return: str; input datetime converted to given format |
134 :return: str; input datetime converted to given format |
134 |
135 |
135 >>> from datetime import datetime |
136 >>> from datetime import datetime |
136 >>> from pyams_utils.date import format_datetime, SH_DATETIME_FORMAT |
137 >>> from pyams_utils.date import format_datetime, SH_DATETIME_FORMAT |
138 >>> format_datetime(value) |
139 >>> format_datetime(value) |
139 'on 15/11/2016 at 10:13' |
140 'on 15/11/2016 at 10:13' |
140 >>> format_datetime(value, SH_DATETIME_FORMAT) |
141 >>> format_datetime(value, SH_DATETIME_FORMAT) |
141 '15/11/2016 - 10:13' |
142 '15/11/2016 - 10:13' |
142 """ |
143 """ |
143 return format_date(value, format, request) |
144 return format_date(value, format_string, request) |
144 |
145 |
145 |
146 |
146 def get_age(value, request=None): |
147 def get_age(value, request=None): |
147 """Get 'human' age of a given datetime (including timezone) compared to current datetime (in UTC) |
148 """Get 'human' age of a given datetime (including timezone) compared to current datetime |
|
149 (in UTC) |
148 |
150 |
149 :param datetime value: input datetime to be compared with current datetime |
151 :param datetime value: input datetime to be compared with current datetime |
150 :return: str; the delta value, converted to months, weeks, days, hours or minutes |
152 :return: str; the delta value, converted to months, weeks, days, hours or minutes |
151 """ |
153 """ |
152 if request is None: |
154 if request is None: |
153 request = check_request() |
155 request = check_request() |
154 translate = request.localizer.translate |
156 translate = request.localizer.translate |
155 now = gmtime(datetime.utcnow()) |
157 now = gmtime(datetime.utcnow()) |
156 delta = now - gmtime(value) |
158 delta = now - gmtime(value) |
157 if delta.days > 60: |
159 if delta.days > 60: |
158 return translate(_("%d months ago")) % int(round(delta.days * 1.0 / 30)) |
160 result = translate(_("%d months ago")) % int(round(delta.days * 1.0 / 30)) |
159 elif delta.days > 10: |
161 elif delta.days > 10: |
160 return translate(_("%d weeks ago")) % int(round(delta.days * 1.0 / 7)) |
162 result = translate(_("%d weeks ago")) % int(round(delta.days * 1.0 / 7)) |
161 elif delta.days > 2: |
163 elif delta.days > 2: |
162 return translate(_("%d days ago")) % delta.days |
164 result = translate(_("%d days ago")) % delta.days |
163 elif delta.days == 2: |
165 elif delta.days == 2: |
164 return translate(_("the day before yesterday")) |
166 result = translate(_("the day before yesterday")) |
165 elif delta.days == 1: |
167 elif delta.days == 1: |
166 return translate(_("yesterday")) |
168 result = translate(_("yesterday")) |
167 else: |
169 else: # less than one day |
168 hours = int(round(delta.seconds * 1.0 / 3600)) |
170 hours = int(round(delta.seconds * 1.0 / 3600)) |
169 if hours > 1: |
171 if hours > 1: |
170 return translate(_("%d hours ago")) % hours |
172 result = translate(_("%d hours ago")) % hours |
171 elif delta.seconds > 300: |
173 elif delta.seconds > 300: |
172 return translate(_("%d minutes ago")) % int(round(delta.seconds * 1.0 / 60)) |
174 result = translate(_("%d minutes ago")) % int(round(delta.seconds * 1.0 / 60)) |
173 else: |
175 else: |
174 return translate(_("less than 5 minutes ago")) |
176 result = translate(_("less than 5 minutes ago")) |
175 |
177 return result |
176 |
178 |
177 def get_duration(v1, v2=None, request=None): |
179 |
|
180 def get_duration(first, last=None, request=None): # pylint: disable=too-many-branches |
178 """Get 'human' delta as string between two dates |
181 """Get 'human' delta as string between two dates |
179 |
182 |
180 :param datetime v1: start date |
183 :param datetime first: start date |
181 :param datetime v2: end date, or current date (in UTC) if None |
184 :param datetime last: end date, or current date (in UTC) if None |
182 :param request: the request from which to extract localization infos |
185 :param request: the request from which to extract localization infos |
183 :return: str; approximate delta between the two input dates |
186 :return: str; approximate delta between the two input dates |
184 |
187 |
185 >>> from datetime import datetime |
188 >>> from datetime import datetime |
186 >>> from pyams_utils.date import get_duration |
189 >>> from pyams_utils.date import get_duration |
219 '75 minutes' |
222 '75 minutes' |
220 >>> date2 = datetime(2015, 1, 1, 0, 0, 15) |
223 >>> date2 = datetime(2015, 1, 1, 0, 0, 15) |
221 >>> get_duration(date1, date2, request) |
224 >>> get_duration(date1, date2, request) |
222 '15 seconds' |
225 '15 seconds' |
223 """ |
226 """ |
224 if v2 is None: |
227 if last is None: |
225 v2 = datetime.utcnow() |
228 last = datetime.utcnow() |
226 assert isinstance(v1, datetime) and isinstance(v2, datetime) |
229 assert isinstance(first, datetime) and isinstance(last, datetime) |
227 if request is None: |
230 if request is None: |
228 request = check_request() |
231 request = check_request() |
229 translate = request.localizer.translate |
232 translate = request.localizer.translate |
230 v1, v2 = min(v1, v2), max(v1, v2) |
233 first, last = min(first, last), max(first, last) |
231 delta = v2 - v1 |
234 delta = last - first |
232 if delta.days > 60: |
235 if delta.days > 60: |
233 return translate(_("%d months")) % int(round(delta.days * 1.0 / 30)) |
236 result = translate(_("%d months")) % int(round(delta.days * 1.0 / 30)) |
234 elif delta.days > 10: |
237 elif delta.days > 10: |
235 return translate(_("%d weeks")) % int(round(delta.days * 1.0 / 7)) |
238 result = translate(_("%d weeks")) % int(round(delta.days * 1.0 / 7)) |
236 elif delta.days >= 2: |
239 elif delta.days >= 2: |
237 return translate(_("%d days")) % delta.days |
240 result = translate(_("%d days")) % delta.days |
238 else: |
241 else: |
239 hours = int(round(delta.seconds * 1.0 / 3600)) |
242 hours = int(round(delta.seconds * 1.0 / 3600)) |
240 if delta.days == 1: |
243 if delta.days == 1: |
241 if hours == 0: |
244 if hours == 0: |
242 return translate(_("24 hours")) |
245 result = translate(_("24 hours")) |
243 else: |
246 else: |
244 return translate(_("%d day and %d hours")) % (delta.days, hours) |
247 result = translate(_("%d day and %d hours")) % (delta.days, hours) |
245 else: |
248 else: |
246 if hours > 2: |
249 if hours > 2: |
247 return translate(_("%d hours")) % hours |
250 result = translate(_("%d hours")) % hours |
248 else: |
251 else: |
249 minutes = int(round(delta.seconds * 1.0 / 60)) |
252 minutes = int(round(delta.seconds * 1.0 / 60)) |
250 if minutes > 2: |
253 if minutes > 2: |
251 return translate(_("%d minutes")) % minutes |
254 result = translate(_("%d minutes")) % minutes |
252 else: |
255 else: |
253 return translate(_("%d seconds")) % delta.seconds |
256 result = translate(_("%d seconds")) % delta.seconds |
254 |
257 return result |
255 |
258 |
256 @adapter_config(name='timestamp', context=(Interface, Interface, Interface), provides=ITALESExtension) |
259 |
|
260 @adapter_config(name='timestamp', context=(Interface, Interface, Interface), |
|
261 provides=ITALESExtension) |
257 class TimestampTalesAdapter(ContextRequestViewAdapter): |
262 class TimestampTalesAdapter(ContextRequestViewAdapter): |
258 """extension:timestamp(context) TALES adapter |
263 """extension:timestamp(context) TALES adapter |
259 |
264 |
260 A PyAMS TALES extension to get timestamp based on last context modification date. |
265 A PyAMS TALES extension to get timestamp based on last context modification date. |
261 """ |
266 """ |
262 |
267 |
263 def render(self, context=None, formatting=None): |
268 def render(self, context=None, formatting=None): |
|
269 """Render TALES extension""" |
264 if context is None: |
270 if context is None: |
265 context = self.request.context |
271 context = self.request.context |
266 if formatting == 'iso': |
272 if formatting == 'iso': |
267 format_func = datetime.isoformat |
273 format_func = datetime.isoformat |
268 else: |
274 else: |
269 format_func = datetime.timestamp |
275 format_func = datetime.timestamp |
270 dc = IZopeDublinCore(context, None) |
276 zdc = IZopeDublinCore(context, None) |
271 if dc is None: |
277 if zdc is None: |
272 return format_func(tztime(datetime.utcnow())) |
278 return format_func(tztime(zdc.modified)) |
273 else: |
279 return format_func(tztime(datetime.utcnow())) |
274 return format_func(tztime(dc.modified)) |
|