Merge pull request #9110 from remitamine/parse_duration
authorSergey M <dstftw@gmail.com>
Thu, 21 Apr 2016 15:53:16 +0000 (22:53 +0700)
committerSergey M <dstftw@gmail.com>
Thu, 21 Apr 2016 15:53:16 +0000 (22:53 +0700)
[utils] imporove parse_duration to handle more formats

1  2 
test/test_utils.py
youtube_dl/utils.py

diff --combined test/test_utils.py
index 0f36bb9f0a40d665ed88220d4f8105710570aaf9,e0323a5c6a5ceabbe7e52e39a94e5b9d8efc81a5..e16a6761b7e9a70589c6da7b48c9f54e2c03e734
@@@ -20,7 -20,6 +20,7 @@@ from youtube_dl.utils import 
      args_to_str,
      encode_base_n,
      clean_html,
 +    date_from_str,
      DateRange,
      detect_exe_version,
      determine_ext,
@@@ -235,13 -234,6 +235,13 @@@ class TestUtil(unittest.TestCase)
          self.assertEqual(unescapeHTML('&eacute;'), 'é')
          self.assertEqual(unescapeHTML('&#2013266066;'), '&#2013266066;')
  
 +    def test_date_from_str(self):
 +        self.assertEqual(date_from_str('yesterday'), date_from_str('now-1day'))
 +        self.assertEqual(date_from_str('now+7day'), date_from_str('now+1week'))
 +        self.assertEqual(date_from_str('now+14day'), date_from_str('now+2week'))
 +        self.assertEqual(date_from_str('now+365day'), date_from_str('now+1year'))
 +        self.assertEqual(date_from_str('now+30day'), date_from_str('now+1month'))
 +
      def test_daterange(self):
          _20century = DateRange("19000101", "20000101")
          self.assertFalse("17890714" in _20century)
          self.assertEqual(parse_duration('01:02:03:04'), 93784)
          self.assertEqual(parse_duration('1 hour 3 minutes'), 3780)
          self.assertEqual(parse_duration('87 Min.'), 5220)
+         self.assertEqual(parse_duration('PT1H0.040S'), 3600.04)
  
      def test_fix_xml_ampersands(self):
          self.assertEqual(
diff --combined youtube_dl/utils.py
index 999dfabb59a5bceb88b4423f0cc91abc81eefc3e,c91aa068217539558e1f32599fa0d5e5b3d6bf60..f333e471275a69cbd158828c90f0ed1b5522582f
@@@ -1540,44 -1540,46 +1540,46 @@@ def parse_duration(s)
  
      s = s.strip()
  
-     m = re.match(
-         r'''(?ix)(?:P?T)?
-         (?:
-             (?P<only_mins>[0-9.]+)\s*(?:mins?\.?|minutes?)\s*|
-             (?P<only_hours>[0-9.]+)\s*(?:hours?)|
-             \s*(?P<hours_reversed>[0-9]+)\s*(?:[:h]|hours?)\s*(?P<mins_reversed>[0-9]+)\s*(?:[:m]|mins?\.?|minutes?)\s*|
-             (?:
+     days, hours, mins, secs, ms = [None] * 5
+     m = re.match(r'(?:(?:(?:(?P<days>[0-9]+):)?(?P<hours>[0-9]+):)?(?P<mins>[0-9]+):)?(?P<secs>[0-9]+)(?P<ms>\.[0-9]+)?$', s)
+     if m:
+         days, hours, mins, secs, ms = m.groups()
+     else:
+         m = re.match(
+             r'''(?ix)(?:P?T)?
                  (?:
-                     (?:(?P<days>[0-9]+)\s*(?:[:d]|days?)\s*)?
-                     (?P<hours>[0-9]+)\s*(?:[:h]|hours?)\s*
+                     (?P<days>[0-9]+)\s*d(?:ays?)?\s*
                  )?
-                 (?P<mins>[0-9]+)\s*(?:[:m]|mins?|minutes?)\s*
-             )?
-             (?P<secs>[0-9]+)(?P<ms>\.[0-9]+)?\s*(?:s|secs?|seconds?)?
-         )$''', s)
-     if not m:
-         return None
-     res = 0
-     if m.group('only_mins'):
-         return float_or_none(m.group('only_mins'), invscale=60)
-     if m.group('only_hours'):
-         return float_or_none(m.group('only_hours'), invscale=60 * 60)
-     if m.group('secs'):
-         res += int(m.group('secs'))
-     if m.group('mins_reversed'):
-         res += int(m.group('mins_reversed')) * 60
-     if m.group('mins'):
-         res += int(m.group('mins')) * 60
-     if m.group('hours'):
-         res += int(m.group('hours')) * 60 * 60
-     if m.group('hours_reversed'):
-         res += int(m.group('hours_reversed')) * 60 * 60
-     if m.group('days'):
-         res += int(m.group('days')) * 24 * 60 * 60
-     if m.group('ms'):
-         res += float(m.group('ms'))
-     return res
+                 (?:
+                     (?P<hours>[0-9]+)\s*h(?:ours?)?\s*
+                 )?
+                 (?:
+                     (?P<mins>[0-9]+)\s*m(?:in(?:ute)?s?)?\s*
+                 )?
+                 (?:
+                     (?P<secs>[0-9]+)(?P<ms>\.[0-9]+)?\s*s(?:ec(?:ond)?s?)?\s*
+                 )?$''', s)
+         if m:
+             days, hours, mins, secs, ms = m.groups()
+         else:
+             m = re.match(r'(?i)(?:(?P<hours>[0-9.]+)\s*(?:hours?)|(?P<mins>[0-9.]+)\s*(?:mins?\.?|minutes?)\s*)$', s)
+             if m:
+                 hours, mins = m.groups()
+             else:
+                 return None
+     duration = 0
+     if secs:
+         duration += float(secs)
+     if mins:
+         duration += float(mins) * 60
+     if hours:
+         duration += float(hours) * 60 * 60
+     if days:
+         duration += float(days) * 24 * 60 * 60
+     if ms:
+         duration += float(ms)
+     return duration
  
  
  def prepend_extension(filename, ext, expected_real_ext=None):
@@@ -1792,8 -1794,6 +1794,8 @@@ def urlencode_postdata(*args, **kargs)
  
  
  def update_url_query(url, query):
 +    if not query:
 +        return url
      parsed_url = compat_urlparse.urlparse(url)
      qs = compat_parse_qs(parsed_url.query)
      qs.update(query)