|
5 | 5 |
|
6 | 6 | # flake8: noqa
|
7 | 7 | from __future__ import unicode_literals
|
| 8 | +import datetime |
| 9 | +import re |
8 | 10 | from django.core.exceptions import ImproperlyConfigured
|
9 | 11 | from django.conf import settings
|
10 | 12 | from django.utils.encoding import force_text
|
@@ -258,3 +260,75 @@ def apply_markdown(text):
|
258 | 260 | SHORT_SEPARATORS = (b',', b':')
|
259 | 261 | LONG_SEPARATORS = (b', ', b': ')
|
260 | 262 | INDENT_SEPARATORS = (b',', b': ')
|
| 263 | + |
| 264 | + |
| 265 | +if django.VERSION >= (1, 8): |
| 266 | + from django.utils.dateparse import parse_duration |
| 267 | + from django.utils.duration import duration_string |
| 268 | + from django.db.models import DurationField |
| 269 | +else: |
| 270 | + from django.db.models import BigIntegerField |
| 271 | + |
| 272 | + class DurationField(BigIntegerField): |
| 273 | + pass |
| 274 | + |
| 275 | + |
| 276 | + # Backported from django 1.8 |
| 277 | + standard_duration_re = re.compile( |
| 278 | + r'^' |
| 279 | + r'(?:(?P<days>-?\d+) )?' |
| 280 | + r'((?:(?P<hours>\d+):)(?=\d+:\d+))?' |
| 281 | + r'(?:(?P<minutes>\d+):)?' |
| 282 | + r'(?P<seconds>\d+)' |
| 283 | + r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?' |
| 284 | + r'$' |
| 285 | + ) |
| 286 | + |
| 287 | + # Support the sections of ISO 8601 date representation that are accepted by |
| 288 | + # timedelta |
| 289 | + iso8601_duration_re = re.compile( |
| 290 | + r'^P' |
| 291 | + r'(?:(?P<days>\d+(.\d+)?)D)?' |
| 292 | + r'(?:T' |
| 293 | + r'(?:(?P<hours>\d+(.\d+)?)H)?' |
| 294 | + r'(?:(?P<minutes>\d+(.\d+)?)M)?' |
| 295 | + r'(?:(?P<seconds>\d+(.\d+)?)S)?' |
| 296 | + r')?' |
| 297 | + r'$' |
| 298 | + ) |
| 299 | + |
| 300 | + def parse_duration(value): |
| 301 | + """Parses a duration string and returns a datetime.timedelta. |
| 302 | +
|
| 303 | + The preferred format for durations in Django is '%d %H:%M:%S.%f'. |
| 304 | +
|
| 305 | + Also supports ISO 8601 representation. |
| 306 | + """ |
| 307 | + match = standard_duration_re.match(value) |
| 308 | + if not match: |
| 309 | + match = iso8601_duration_re.match(value) |
| 310 | + if match: |
| 311 | + kw = match.groupdict() |
| 312 | + if kw.get('microseconds'): |
| 313 | + kw['microseconds'] = kw['microseconds'].ljust(6, unicode_to_repr('0')) |
| 314 | + kw = dict((k, float(v)) for k, v in six.iteritems(kw) if v is not None) |
| 315 | + return datetime.timedelta(**kw) |
| 316 | + |
| 317 | + def duration_string(duration): |
| 318 | + days = duration.days |
| 319 | + seconds = duration.seconds |
| 320 | + microseconds = duration.microseconds |
| 321 | + |
| 322 | + minutes = seconds // 60 |
| 323 | + seconds = seconds % 60 |
| 324 | + |
| 325 | + hours = minutes // 60 |
| 326 | + minutes = minutes % 60 |
| 327 | + |
| 328 | + string = '{0:02d}:{1:02d}:{2:02d}'.format(hours, minutes, seconds) |
| 329 | + if days: |
| 330 | + string = '{0} '.format(days) + string |
| 331 | + if microseconds: |
| 332 | + string += '.{0:06d}'.format(microseconds) |
| 333 | + |
| 334 | + return string |
0 commit comments