summary refs log tree commit diff
diff options
context:
space:
mode:
authorJaime Marquínez Ferrándiz <jaime.marquinez.ferrandiz@gmail.com>2013-04-27 14:01:55 +0200
committerJaime Marquínez Ferrándiz <jaime.marquinez.ferrandiz@gmail.com>2013-04-27 14:01:55 +0200
commitbd55852517a40d011b303559f4cd78773a2f3de5 (patch)
tree9531a89c70f57cf06c23f39725e084858acb9c81
parent4c9f7a9988f296eeedd0843cded5cbcec3392adb (diff)
downloadyoutube-dl-bd55852517a40d011b303559f4cd78773a2f3de5.tar.gz
youtube-dl-bd55852517a40d011b303559f4cd78773a2f3de5.tar.xz
youtube-dl-bd55852517a40d011b303559f4cd78773a2f3de5.zip
Allow to select videos to download by their upload dates (related #137)
Only absolute dates.
-rw-r--r--test/test_utils.py9
-rw-r--r--youtube_dl/FileDownloader.py6
-rw-r--r--youtube_dl/__init__.py10
-rw-r--r--youtube_dl/utils.py30
4 files changed, 54 insertions, 1 deletions
diff --git a/test/test_utils.py b/test/test_utils.py
index eeaaa7fad..f9d58268b 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -14,6 +14,7 @@ from youtube_dl.utils import timeconvert
 from youtube_dl.utils import sanitize_filename
 from youtube_dl.utils import unescapeHTML
 from youtube_dl.utils import orderedSet
+from youtube_dl.utils import DateRange
 
 if sys.version_info < (3, 0):
     _compat_str = lambda b: b.decode('unicode-escape')
@@ -95,6 +96,14 @@ class TestUtil(unittest.TestCase):
 
     def test_unescape_html(self):
         self.assertEqual(unescapeHTML(_compat_str('%20;')), _compat_str('%20;'))
+        
+    def test_daterange(self):
+        _20century = DateRange("19000101","20000101")
+        self.assertFalse("17890714" in _20century)
+        _ac = DateRange("00010101")
+        self.assertTrue("19690721" in _ac)
+        _firstmilenium = DateRange(end="10000101")
+        self.assertTrue("07110427" in _firstmilenium)
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/youtube_dl/FileDownloader.py b/youtube_dl/FileDownloader.py
index d0378fb14..2db686d62 100644
--- a/youtube_dl/FileDownloader.py
+++ b/youtube_dl/FileDownloader.py
@@ -89,6 +89,7 @@ class FileDownloader(object):
     keepvideo:         Keep the video file after post-processing
     min_filesize:      Skip files smaller than this size
     max_filesize:      Skip files larger than this size
+    daterange:         A DateRange object, download only if the upload_date is in the range.
     """
 
     params = None
@@ -424,6 +425,11 @@ class FileDownloader(object):
         if rejecttitle:
             if re.search(rejecttitle, title, re.IGNORECASE):
                 return u'"' + title + '" title matched reject pattern "' + rejecttitle + '"'
+        date = info_dict.get('upload_date', None)
+        if date is not None:
+            dateRange = self.params.get('daterange', DateRange())
+            if date not in dateRange:
+                return u'[download] %s upload date is not in range %s' % (date_from_str(date).isoformat(), dateRange)
         return None
         
     def extract_info(self, url, download = True, ie_name = None):
diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py
index d491402c6..ce754ffd3 100644
--- a/youtube_dl/__init__.py
+++ b/youtube_dl/__init__.py
@@ -157,6 +157,9 @@ def parseOpts(overrideArguments=None):
     selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None)
     selection.add_option('--min-filesize', metavar='SIZE', dest='min_filesize', help="Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)", default=None)
     selection.add_option('--max-filesize', metavar='SIZE', dest='max_filesize', help="Do not download any videos larger than SIZE (e.g. 50k or 44.6m)", default=None)
+    selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None)
+    selection.add_option('--datebefore', metavar='DATE', dest='datebefore', help='download only videos uploaded before this date', default=None)
+    selection.add_option('--dateafter', metavar='DATE', dest='dateafter', help='download only videos uploaded after this date', default=None)
 
 
     authentication.add_option('-u', '--username',
@@ -447,6 +450,10 @@ def _real_main(argv=None):
     if opts.recodevideo is not None:
         if opts.recodevideo not in ['mp4', 'flv', 'webm', 'ogg']:
             parser.error(u'invalid video recode format specified')
+    if opts.date is not None:
+        date = DateRange.day(opts.date)
+    else:
+        date = DateRange(opts.dateafter, opts.datebefore)
 
     if sys.version_info < (3,):
         # In Python 2, sys.argv is a bytestring (also note http://bugs.python.org/issue2128 for Windows systems)
@@ -513,7 +520,8 @@ def _real_main(argv=None):
         'test': opts.test,
         'keepvideo': opts.keepvideo,
         'min_filesize': opts.min_filesize,
-        'max_filesize': opts.max_filesize
+        'max_filesize': opts.max_filesize,
+        'daterange': date
         })
 
     if opts.verbose:
diff --git a/youtube_dl/utils.py b/youtube_dl/utils.py
index 017f06c42..e5d756b8b 100644
--- a/youtube_dl/utils.py
+++ b/youtube_dl/utils.py
@@ -12,6 +12,7 @@ import traceback
 import zlib
 import email.utils
 import json
+import datetime
 
 try:
     import urllib.request as compat_urllib_request
@@ -568,3 +569,32 @@ class YoutubeDLHandler(compat_urllib_request.HTTPHandler):
 
     https_request = http_request
     https_response = http_response
+    
+def date_from_str(date_str):
+    """Return a datetime object from a string in the format YYYYMMDD"""
+    return datetime.datetime.strptime(date_str, "%Y%m%d").date()
+    
+class DateRange(object):
+    """Represents a time interval between two dates"""
+    def __init__(self, start=None, end=None):
+        """start and end must be strings in the format accepted by date"""
+        if start is not None:
+            self.start = date_from_str(start)
+        else:
+            self.start = datetime.datetime.min.date()
+        if end is not None:
+            self.end = date_from_str(end)
+        else:
+            self.end = datetime.datetime.max.date()
+        if self.start >= self.end:
+            raise ValueError('Date range: "%s" , the start date must be before the end date' % self)
+    @classmethod
+    def day(cls, day):
+        """Returns a range that only contains the given day"""
+        return cls(day,day)
+    def __contains__(self, date):
+        """Check if the date is in the range"""
+        date = date_from_str(date)
+        return self.start <= date and date <= self.end
+    def __str__(self):
+        return '%s - %s' % ( self.start.isoformat(), self.end.isoformat())