Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an easy way to convert ISO 8601 duration to timedelta?

Given a ISO 8601 duration string, how do I convert it into a datetime.timedelta?

This didn't work:

timedelta("PT1H5M26S", "T%H%M%S") 

A timedelta object represents a duration, the difference between two dates or times (https://docs.python.org/3/library/datetime.html#datetime.timedelta). ISO 8601 durations are described here: https://en.wikipedia.org/wiki/ISO_8601#Durations

like image 356
Alkindus Avatar asked May 02 '16 06:05

Alkindus


2 Answers

I found isodate library to do exactly what I want

isodate.parse_duration('PT1H5M26S') 
  • You can read the source code for the function here
like image 101
Alkindus Avatar answered Sep 20 '22 12:09

Alkindus


Here's a solution without a new package, but only works if you're dealing with a max duration expressed in days. That limitation makes sense though, because as others have pointed out (1):

Given that the timedelta has more than "a month's" worth of days, how would you describe it using the ISO8601 duration notation without referencing a specific point in time? Conversely, given your example, "P3Y6M4DT12H30M5S", how would you convert that into a timedelta without knowing which exact years and months this duration refers to? Timedelta objects are very precise beasts, which is almost certainly why they don't support "years" and "months" args in their constructors.

import datetime   def get_isosplit(s, split):     if split in s:         n, s = s.split(split)     else:         n = 0     return n, s   def parse_isoduration(s):              # Remove prefix     s = s.split('P')[-1]          # Step through letter dividers     days, s = get_isosplit(s, 'D')     _, s = get_isosplit(s, 'T')     hours, s = get_isosplit(s, 'H')     minutes, s = get_isosplit(s, 'M')     seconds, s = get_isosplit(s, 'S')      # Convert all to seconds     dt = datetime.timedelta(days=int(days), hours=int(hours), minutes=int(minutes), seconds=int(seconds))     return int(dt.total_seconds()) 
> parse_isoduration("PT1H5M26S") 3926 
like image 22
r3robertson Avatar answered Sep 17 '22 12:09

r3robertson