diff --git a/test/test_playlists.py b/test/test_playlists.py index b1e38e7e9e..4af38632e7 100644 --- a/test/test_playlists.py +++ b/test/test_playlists.py @@ -309,6 +309,8 @@ def test_InstagramUser(self): 'thumbnail': 're:^https?://.*\.jpg', 'uploader': 'Porsche', 'uploader_id': 'porsche', + 'timestamp': 1387486713, + 'upload_date': '20131219', } expect_info_dict(self, EXPECTED, test_video) diff --git a/test/test_utils.py b/test/test_utils.py index 7ee74e36c0..e920d661f6 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -35,6 +35,7 @@ url_basename, urlencode_postdata, xpath_with_ns, + parse_iso8601, ) if sys.version_info < (3, 0): @@ -266,5 +267,10 @@ def test_urlencode_postdata(self): data = urlencode_postdata({'username': 'foo@bar.com', 'password': '1234'}) self.assertTrue(isinstance(data, bytes)) + def test_parse_iso8601(self): + self.assertEqual(parse_iso8601('2014-03-23T23:04:26+0100'), 1395612266) + self.assertEqual(parse_iso8601('2014-03-23T22:04:26+0000'), 1395612266) + self.assertEqual(parse_iso8601('2014-03-23T22:04:26Z'), 1395612266) + if __name__ == '__main__': unittest.main() diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 3e728e8760..245860140b 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -195,6 +195,7 @@ from .rottentomatoes import RottenTomatoesIE from .roxwel import RoxwelIE from .rtlnow import RTLnowIE +from .rts import RTSIE from .rutube import ( RutubeIE, RutubeChannelIE, diff --git a/youtube_dl/extractor/instagram.py b/youtube_dl/extractor/instagram.py index 994f0e4aef..b5372bf7a2 100644 --- a/youtube_dl/extractor/instagram.py +++ b/youtube_dl/extractor/instagram.py @@ -89,7 +89,7 @@ def _real_extract(self, url): 'uploader': user.get('full_name'), 'uploader_id': user.get('username'), 'like_count': like_count, - 'upload_timestamp': int_or_none(it.get('created_time')), + 'timestamp': int_or_none(it.get('created_time')), }) if not page['items']: diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py index 8b359cb77f..68d590ba25 100644 --- a/youtube_dl/utils.py +++ b/youtube_dl/utils.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import calendar import contextlib import ctypes import datetime @@ -501,13 +502,13 @@ def orderedSet(iterable): res.append(el) return res -def unescapeHTML(s): - """ - @param s a string - """ - assert type(s) == type(u'') - result = re.sub(u'(?u)&(.+?);', htmlentity_transform, s) +def unescapeHTML(s): + if s is None: + return None + assert type(s) == compat_str + + result = re.sub(r'(?u)&(.+?);', htmlentity_transform, s) return result @@ -761,6 +762,31 @@ def http_response(self, req, resp): https_response = http_response +def parse_iso8601(date_str): + """ Return a UNIX timestamp from the given date """ + + if date_str is None: + return None + + m = re.search( + r'Z$| ?(?P\+|-)(?P[0-9]{2}):?(?P[0-9]{2})$', + date_str) + if not m: + timezone = datetime.timedelta() + else: + date_str = date_str[:-len(m.group(0))] + if not m.group('sign'): + timezone = datetime.timedelta() + else: + sign = 1 if m.group('sign') == '+' else -1 + timezone = datetime.timedelta( + hours=sign * int(m.group('hours')), + minutes=sign * int(m.group('minutes'))) + + dt = datetime.datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S') - timezone + return calendar.timegm(dt.timetuple()) + + def unified_strdate(date_str): """Return a string with the date in the format YYYYMMDD"""