Opened 9 years ago
Closed 5 years ago
#25060 closed New feature (fixed)
Add support for str(timedelta) representation in parse_duration
Reported by: | Mikhail | Owned by: | nobody |
---|---|---|---|
Component: | Utilities | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Mikhail, Marc Tamlyn | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | yes |
Needs tests: | yes | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It's useful for conversions to/from str, so we can convert timedelta value to str and back without additional work.
The following code can be used instead of original parse_duration function
# Support str(timedelta) format str_timedelta_duration_re = re.compile( r'^' r'(?:(?P<days>-?\d+) days*, )?' r'((?:(?P<hours>\d+):)(?=\d+:\d+))?' r'(?:(?P<minutes>\d+):)?' r'(?P<seconds>\d+)' r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?' r'$' ) def parse_duration(value): """Parses a duration string and returns a datetime.timedelta. The preferred format for durations in Django is '%d %H:%M:%S.%f'. Also supports ISO 8601 and str(timedelta) representations. """ for duration_re in (standard_duration_re, iso8601_duration_re, str_timedelta_duration_re): match = duration_re.match(value) if match: kw = match.groupdict() if kw.get('microseconds'): kw['microseconds'] = kw['microseconds'].ljust(6, '0') kw = {k: float(v) for k, v in six.iteritems(kw) if v is not None} return datetime.timedelta(**kw)
Change History (10)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Cc: | added |
---|
My specific use case is DurationField
in django-hstore schema mode (but I suppose it can be useful in other situations).
Without this patch to_python()
raise an error about inappropriate format. I agree that in my use case it's preferable to use duration_string()
instead of str()
for conversion, but I still didn't find the place where I can override this behavior on django-hstore side :).
Seems now I understand why you don't implement it, str(timedelta)
output can be locale dependent. If so this patch is controversial point.
comment:4 by , 9 years ago
Have you raised the issue with django-hstore? I wonder if it should be calling the form field prepare_value() method?
comment:5 by , 9 years ago
For now - no. DurationField is not in the list of officially supported field types, docs say that some other fields can work as well but some of them need additional work. Seems for other types str()
method is called by default. So DurationField support is just new feature for django-hstore. I'm working on support of additional fields but not as the part of django.
I've put parse_duration()
patch here because I thought it can be useful for django core itself. English specificity can be avoided using more versatile regex like:
str_timedelta_duration_re = re.compile( r'^' r'(?:(?P<days>-?\d+) \w+, )?' r'((?:(?P<hours>\d+):)(?=\d+:\d+))?' r'(?:(?P<minutes>\d+):)?' r'(?P<seconds>\d+)' r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?' r'$' )
comment:7 by , 9 years ago
I can see the merit in supporting the the str(timedelta) format in English. The intention was to encourage locale independent representation of the timedelta. I am completely unfamiliar with what str(timedelta) does in other locales, if we could support it generically that would be great.
comment:8 by , 9 years ago
Seems str(timedelta) output is locale independent. I've checked on several locales and all the time output is the same.
>>> for loc in ('ar_AE', 'ar_BH', 'ar_DZ', 'ar_EG', 'ar_IN', 'ar_IQ', 'ar_JO', 'ar_KW', 'ar_LB', 'ar_LY', 'ar_MA', 'ar_OM', 'ar_QA', 'ar_SA', 'ar_SD', 'ar_SY', 'ar_TN', 'ar_YE', 'C', 'de_AT', 'de_BE', 'de_CH', 'de_DE', 'de_LI', 'de_LU', 'en_AG', 'en_AU', 'en_BW', 'en_CA', 'en_DK', 'en_GB', 'en_HK', 'en_IE', 'en_IN', 'en_NG', 'en_NZ', 'en_PH', 'en_SG', 'en_US', 'en_ZA', 'en_ZM', 'en_ZW', 'it_CH', 'it_IT', 'ja_JP', 'ko_KR', 'mr_IN', 'POSIX', 'ru_RU', 'ru_UA', 'sa_IN', 'tr_CY', 'tr_TR', 'zh_HK', 'zh_TW', 'zu_ZA', ): ... locale.setlocale(locale.LC_ALL, (loc, 'utf-8')) ... str(timedelta(777, 0, 1)) ... 'ar_AE.UTF-8' '777 days, 0:00:00.000001' 'ar_BH.UTF-8' '777 days, 0:00:00.000001' etc....
Also there are some topics in web about formating str(timedelta) according to locale, it shows str(timedelta) is locale independent. So, I suppose, we can use English regex.
comment:9 by , 9 years ago
Easy pickings: | unset |
---|---|
Needs documentation: | set |
Needs tests: | set |
Triage Stage: | Unreviewed → Accepted |
Version: | 1.8 → master |
The patch also requires tests and documentation updates. See also the patch review checklist.
comment:11 by , 5 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Replying to Matthew Schinckel:
I think the parse_duration() function already does this.
That's correct. It looks like this was inadvertently added with #24897 (262d4db8c4c849b0fdd84550fb96472446cf90df).
There are even tests for a variety of different timedelta
cases: https://github.com/django/django/blob/a5855c8f0fe17b7e888bd8137874ef78012a7294/tests/utils_tests/test_dateparse.py#L54
Can you elaborate on your use case a bit?
parse_duration()
is currently the inverse ofdjango.utils.duration.duration_string()
which is not English specific. Maybe you can use that function instead ofstr()
.