We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[APP SUBMITTED]: ValueError: hour must be in 0..23
### INFO
**Python Version**: `2.7.9 (default, Sep 17 2016, 20:26:04) [GCC 4.9.2]`
**Operating System**: `Linux-4.4.38-v7+-armv7l-with-debian-8.0`
**Locale**: `UTF-8`
**Branch**: [develop](../tree/develop)
**Database**: `44.8`
**Commit**: pymedusa/Medusa@94e0649919e9e05ac380f8e6d3817c18255931ee
**Link to Log**: https://gist.github.com/31ec35e671692a5cc7ba13b4d2d07353
### ERROR
<pre>
2017-05-30 15:24:07 ERROR    SEARCHQUEUE-BACKLOG-75340 :: [TorrentProject] :: [94e0649] Failed parsing publishing date: 24 hours ago
Traceback (most recent call last):
  File "/home/pi/Medusa/<a href="../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/medusa/providers/generic_provider.py#L512">medusa/providers/generic_provider.py</a>", line 512, in parse_pubdate
    dt = parser.parse(pubdate, fuzzy=True)
  File "/home/pi/Medusa/<a href="../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/lib/dateutil/parser.py#L1181">lib/dateutil/parser.py</a>", line 1181, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/home/pi/Medusa/<a href="../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/lib/dateutil/parser.py#L584">lib/dateutil/parser.py</a>", line 584, in parse
    ret = default.replace(**repl)
ValueError: hour must be in 0..23
</pre>
---
_STAFF NOTIFIED_: @pymedusa/support @pymedusa/moderators

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `medusa/providers/torrent/html/torrentproject.py`
Content:
```
1 # coding=utf-8
2 
3 """Provider code for TorrentProject."""
4 
5 from __future__ import unicode_literals
6 
7 import logging
8 import traceback
9 
10 from medusa import tv
11 from medusa.bs4_parser import BS4Parser
12 from medusa.common import USER_AGENT
13 from medusa.helper.common import (
14     convert_size,
15     try_int,
16 )
17 from medusa.logger.adapters.style import BraceAdapter
18 from medusa.providers.torrent.torrent_provider import TorrentProvider
19 
20 import validators
21 
22 log = BraceAdapter(logging.getLogger(__name__))
23 log.logger.addHandler(logging.NullHandler())
24 
25 
26 class TorrentProjectProvider(TorrentProvider):
27     """TorrentProject Torrent provider."""
28 
29     def __init__(self):
30         """Initialize the class."""
31         super(TorrentProjectProvider, self).__init__('TorrentProject')
32 
33         # Credentials
34         self.public = True
35 
36         # URLs
37         self.url = 'https://torrentproject.se'
38         self.custom_url = None
39 
40         # Proper Strings
41 
42         # Miscellaneous Options
43         self.headers.update({'User-Agent': USER_AGENT})
44 
45         # Torrent Stats
46         self.minseed = None
47         self.minleech = None
48 
49         # Cache
50         self.cache = tv.Cache(self, min_time=20)
51 
52     def search(self, search_strings, age=0, ep_obj=None):
53         """
54         Search a provider and parse the results.
55 
56         :param search_strings: A dict with mode (key) and the search value (value)
57         :param age: Not used
58         :param ep_obj: Not used
59         :returns: A list of search results (structure)
60         """
61         results = []
62 
63         if self.custom_url:
64             if not validators.url(self.custom_url):
65                 log.warning('Invalid custom url: {0}', self.custom_url)
66                 return results
67             search_url = self.custom_url
68         else:
69             search_url = self.url
70 
71         search_params = {
72             'hl': 'en',
73             'num': 40,
74             'start': 0,
75             'filter': 2101,
76             'safe': 'on',
77             'orderby': 'latest',
78             's': '',
79         }
80 
81         for mode in search_strings:
82             log.debug('Search mode: {0}', mode)
83 
84             for search_string in search_strings[mode]:
85                 if mode != 'RSS':
86                     search_params['s'] = search_string
87                     log.debug('Search string: {search}',
88                               {'search': search_string})
89 
90                 response = self.get_url(search_url, params=search_params, returns='response')
91                 if not response or not response.text:
92                     log.debug('No data returned from provider')
93                     continue
94 
95                 results += self.parse(response.text, mode)
96 
97         return results
98 
99     def parse(self, data, mode):
100         """
101         Parse search results for items.
102 
103         :param data: The raw response from a search
104         :param mode: The current mode used to search, e.g. RSS
105 
106         :return: A list of items found
107         """
108         items = []
109 
110         with BS4Parser(data, 'html5lib') as html:
111             torrent_rows = html.find_all('div', class_='torrent')
112 
113             # Continue only if at least one release is found
114             if not torrent_rows:
115                 log.debug('Data returned from provider does not contain any torrents')
116                 return items
117 
118             for row in torrent_rows:
119                 anchor = row.find('a')
120 
121                 try:
122                     # Removes ' torrent' in the end
123                     title = anchor.get('title')[:-8]
124                     download_url = anchor.get('href')
125                     if not all([title, download_url]):
126                         continue
127 
128                     info_hash = download_url.split('/')[1]
129                     download_url = 'magnet:?xt=urn:btih:{hash}&dn={title}{trackers}'.format(
130                         hash=info_hash, title=title, trackers=self._custom_trackers)
131 
132                     seeders = try_int(row.find('span', class_='bc seeders').find('span').get_text(), 1)
133                     leechers = try_int(row.find('span', class_='bc leechers').find('span').get_text())
134 
135                     # Filter unseeded torrent
136                     if seeders < min(self.minseed, 1):
137                         if mode != 'RSS':
138                             log.debug("Discarding torrent because it doesn't meet the"
139                                       " minimum seeders: {0}. Seeders: {1}",
140                                       title, seeders)
141                         continue
142 
143                     torrent_size = row.find('span', class_='bc torrent-size').get_text().rstrip()
144                     size = convert_size(torrent_size) or -1
145 
146                     pubdate_raw = row.find('span', class_='bc cated').get_text(strip=True)
147                     pubdate = self.parse_pubdate(pubdate_raw)
148 
149                     item = {
150                         'title': title,
151                         'link': download_url,
152                         'size': size,
153                         'seeders': seeders,
154                         'leechers': leechers,
155                         'pubdate': pubdate,
156                     }
157                     if mode != 'RSS':
158                         log.debug('Found result: {0} with {1} seeders and {2} leechers',
159                                   title, seeders, leechers)
160 
161                     items.append(item)
162                 except (AttributeError, TypeError, KeyError, ValueError, IndexError):
163                     log.error('Failed parsing provider. Traceback: {0!r}',
164                               traceback.format_exc())
165 
166             return items
167 
168 
169 provider = TorrentProjectProvider()
170
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/medusa/providers/torrent/html/torrentproject.py b/medusa/providers/torrent/html/torrentproject.py
--- a/medusa/providers/torrent/html/torrentproject.py
+++ b/medusa/providers/torrent/html/torrentproject.py
@@ -144,7 +144,7 @@
                     size = convert_size(torrent_size) or -1
 
                     pubdate_raw = row.find('span', class_='bc cated').get_text(strip=True)
-                    pubdate = self.parse_pubdate(pubdate_raw)
+                    pubdate = self.parse_pubdate(pubdate_raw, human_time=True)
 
                     item = {
                         'title': title,

{"golden_diff": "diff --git a/medusa/providers/torrent/html/torrentproject.py b/medusa/providers/torrent/html/torrentproject.py\n--- a/medusa/providers/torrent/html/torrentproject.py\n+++ b/medusa/providers/torrent/html/torrentproject.py\n@@ -144,7 +144,7 @@\n                     size = convert_size(torrent_size) or -1\n \n                     pubdate_raw = row.find('span', class_='bc cated').get_text(strip=True)\n-                    pubdate = self.parse_pubdate(pubdate_raw)\n+                    pubdate = self.parse_pubdate(pubdate_raw, human_time=True)\n \n                     item = {\n                         'title': title,\n", "issue": "[APP SUBMITTED]: ValueError: hour must be in 0..23\n### INFO\n**Python Version**: `2.7.9 (default, Sep 17 2016, 20:26:04) [GCC 4.9.2]`\n**Operating System**: `Linux-4.4.38-v7+-armv7l-with-debian-8.0`\n**Locale**: `UTF-8`\n**Branch**: [develop](../tree/develop)\n**Database**: `44.8`\n**Commit**: pymedusa/Medusa@94e0649919e9e05ac380f8e6d3817c18255931ee\n**Link to Log**: https://gist.github.com/31ec35e671692a5cc7ba13b4d2d07353\n### ERROR\n<pre>\n2017-05-30 15:24:07 ERROR    SEARCHQUEUE-BACKLOG-75340 :: [TorrentProject] :: [94e0649] Failed parsing publishing date: 24 hours ago\nTraceback (most recent call last):\n  File \"/home/pi/Medusa/<a href=\"../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/medusa/providers/generic_provider.py#L512\">medusa/providers/generic_provider.py</a>\", line 512, in parse_pubdate\n    dt = parser.parse(pubdate, fuzzy=True)\n  File \"/home/pi/Medusa/<a href=\"../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/lib/dateutil/parser.py#L1181\">lib/dateutil/parser.py</a>\", line 1181, in parse\n    return DEFAULTPARSER.parse(timestr, **kwargs)\n  File \"/home/pi/Medusa/<a href=\"../blob/94e0649919e9e05ac380f8e6d3817c18255931ee/lib/dateutil/parser.py#L584\">lib/dateutil/parser.py</a>\", line 584, in parse\n    ret = default.replace(**repl)\nValueError: hour must be in 0..23\n</pre>\n---\n_STAFF NOTIFIED_: @pymedusa/support @pymedusa/moderators\n", "before_files": [{"content": "# coding=utf-8\n\n\"\"\"Provider code for TorrentProject.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport logging\nimport traceback\n\nfrom medusa import tv\nfrom medusa.bs4_parser import BS4Parser\nfrom medusa.common import USER_AGENT\nfrom medusa.helper.common import (\n    convert_size,\n    try_int,\n)\nfrom medusa.logger.adapters.style import BraceAdapter\nfrom medusa.providers.torrent.torrent_provider import TorrentProvider\n\nimport validators\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\n\nclass TorrentProjectProvider(TorrentProvider):\n    \"\"\"TorrentProject Torrent provider.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the class.\"\"\"\n        super(TorrentProjectProvider, self).__init__('TorrentProject')\n\n        # Credentials\n        self.public = True\n\n        # URLs\n        self.url = 'https://torrentproject.se'\n        self.custom_url = None\n\n        # Proper Strings\n\n        # Miscellaneous Options\n        self.headers.update({'User-Agent': USER_AGENT})\n\n        # Torrent Stats\n        self.minseed = None\n        self.minleech = None\n\n        # Cache\n        self.cache = tv.Cache(self, min_time=20)\n\n    def search(self, search_strings, age=0, ep_obj=None):\n        \"\"\"\n        Search a provider and parse the results.\n\n        :param search_strings: A dict with mode (key) and the search value (value)\n        :param age: Not used\n        :param ep_obj: Not used\n        :returns: A list of search results (structure)\n        \"\"\"\n        results = []\n\n        if self.custom_url:\n            if not validators.url(self.custom_url):\n                log.warning('Invalid custom url: {0}', self.custom_url)\n                return results\n            search_url = self.custom_url\n        else:\n            search_url = self.url\n\n        search_params = {\n            'hl': 'en',\n            'num': 40,\n            'start': 0,\n            'filter': 2101,\n            'safe': 'on',\n            'orderby': 'latest',\n            's': '',\n        }\n\n        for mode in search_strings:\n            log.debug('Search mode: {0}', mode)\n\n            for search_string in search_strings[mode]:\n                if mode != 'RSS':\n                    search_params['s'] = search_string\n                    log.debug('Search string: {search}',\n                              {'search': search_string})\n\n                response = self.get_url(search_url, params=search_params, returns='response')\n                if not response or not response.text:\n                    log.debug('No data returned from provider')\n                    continue\n\n                results += self.parse(response.text, mode)\n\n        return results\n\n    def parse(self, data, mode):\n        \"\"\"\n        Parse search results for items.\n\n        :param data: The raw response from a search\n        :param mode: The current mode used to search, e.g. RSS\n\n        :return: A list of items found\n        \"\"\"\n        items = []\n\n        with BS4Parser(data, 'html5lib') as html:\n            torrent_rows = html.find_all('div', class_='torrent')\n\n            # Continue only if at least one release is found\n            if not torrent_rows:\n                log.debug('Data returned from provider does not contain any torrents')\n                return items\n\n            for row in torrent_rows:\n                anchor = row.find('a')\n\n                try:\n                    # Removes ' torrent' in the end\n                    title = anchor.get('title')[:-8]\n                    download_url = anchor.get('href')\n                    if not all([title, download_url]):\n                        continue\n\n                    info_hash = download_url.split('/')[1]\n                    download_url = 'magnet:?xt=urn:btih:{hash}&dn={title}{trackers}'.format(\n                        hash=info_hash, title=title, trackers=self._custom_trackers)\n\n                    seeders = try_int(row.find('span', class_='bc seeders').find('span').get_text(), 1)\n                    leechers = try_int(row.find('span', class_='bc leechers').find('span').get_text())\n\n                    # Filter unseeded torrent\n                    if seeders < min(self.minseed, 1):\n                        if mode != 'RSS':\n                            log.debug(\"Discarding torrent because it doesn't meet the\"\n                                      \" minimum seeders: {0}. Seeders: {1}\",\n                                      title, seeders)\n                        continue\n\n                    torrent_size = row.find('span', class_='bc torrent-size').get_text().rstrip()\n                    size = convert_size(torrent_size) or -1\n\n                    pubdate_raw = row.find('span', class_='bc cated').get_text(strip=True)\n                    pubdate = self.parse_pubdate(pubdate_raw)\n\n                    item = {\n                        'title': title,\n                        'link': download_url,\n                        'size': size,\n                        'seeders': seeders,\n                        'leechers': leechers,\n                        'pubdate': pubdate,\n                    }\n                    if mode != 'RSS':\n                        log.debug('Found result: {0} with {1} seeders and {2} leechers',\n                                  title, seeders, leechers)\n\n                    items.append(item)\n                except (AttributeError, TypeError, KeyError, ValueError, IndexError):\n                    log.error('Failed parsing provider. Traceback: {0!r}',\n                              traceback.format_exc())\n\n            return items\n\n\nprovider = TorrentProjectProvider()\n", "path": "medusa/providers/torrent/html/torrentproject.py"}], "after_files": [{"content": "# coding=utf-8\n\n\"\"\"Provider code for TorrentProject.\"\"\"\n\nfrom __future__ import unicode_literals\n\nimport logging\nimport traceback\n\nfrom medusa import tv\nfrom medusa.bs4_parser import BS4Parser\nfrom medusa.common import USER_AGENT\nfrom medusa.helper.common import (\n    convert_size,\n    try_int,\n)\nfrom medusa.logger.adapters.style import BraceAdapter\nfrom medusa.providers.torrent.torrent_provider import TorrentProvider\n\nimport validators\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\n\nclass TorrentProjectProvider(TorrentProvider):\n    \"\"\"TorrentProject Torrent provider.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize the class.\"\"\"\n        super(TorrentProjectProvider, self).__init__('TorrentProject')\n\n        # Credentials\n        self.public = True\n\n        # URLs\n        self.url = 'https://torrentproject.se'\n        self.custom_url = None\n\n        # Proper Strings\n\n        # Miscellaneous Options\n        self.headers.update({'User-Agent': USER_AGENT})\n\n        # Torrent Stats\n        self.minseed = None\n        self.minleech = None\n\n        # Cache\n        self.cache = tv.Cache(self, min_time=20)\n\n    def search(self, search_strings, age=0, ep_obj=None):\n        \"\"\"\n        Search a provider and parse the results.\n\n        :param search_strings: A dict with mode (key) and the search value (value)\n        :param age: Not used\n        :param ep_obj: Not used\n        :returns: A list of search results (structure)\n        \"\"\"\n        results = []\n\n        if self.custom_url:\n            if not validators.url(self.custom_url):\n                log.warning('Invalid custom url: {0}', self.custom_url)\n                return results\n            search_url = self.custom_url\n        else:\n            search_url = self.url\n\n        search_params = {\n            'hl': 'en',\n            'num': 40,\n            'start': 0,\n            'filter': 2101,\n            'safe': 'on',\n            'orderby': 'latest',\n            's': '',\n        }\n\n        for mode in search_strings:\n            log.debug('Search mode: {0}', mode)\n\n            for search_string in search_strings[mode]:\n                if mode != 'RSS':\n                    search_params['s'] = search_string\n                    log.debug('Search string: {search}',\n                              {'search': search_string})\n\n                response = self.get_url(search_url, params=search_params, returns='response')\n                if not response or not response.text:\n                    log.debug('No data returned from provider')\n                    continue\n\n                results += self.parse(response.text, mode)\n\n        return results\n\n    def parse(self, data, mode):\n        \"\"\"\n        Parse search results for items.\n\n        :param data: The raw response from a search\n        :param mode: The current mode used to search, e.g. RSS\n\n        :return: A list of items found\n        \"\"\"\n        items = []\n\n        with BS4Parser(data, 'html5lib') as html:\n            torrent_rows = html.find_all('div', class_='torrent')\n\n            # Continue only if at least one release is found\n            if not torrent_rows:\n                log.debug('Data returned from provider does not contain any torrents')\n                return items\n\n            for row in torrent_rows:\n                anchor = row.find('a')\n\n                try:\n                    # Removes ' torrent' in the end\n                    title = anchor.get('title')[:-8]\n                    download_url = anchor.get('href')\n                    if not all([title, download_url]):\n                        continue\n\n                    info_hash = download_url.split('/')[1]\n                    download_url = 'magnet:?xt=urn:btih:{hash}&dn={title}{trackers}'.format(\n                        hash=info_hash, title=title, trackers=self._custom_trackers)\n\n                    seeders = try_int(row.find('span', class_='bc seeders').find('span').get_text(), 1)\n                    leechers = try_int(row.find('span', class_='bc leechers').find('span').get_text())\n\n                    # Filter unseeded torrent\n                    if seeders < min(self.minseed, 1):\n                        if mode != 'RSS':\n                            log.debug(\"Discarding torrent because it doesn't meet the\"\n                                      \" minimum seeders: {0}. Seeders: {1}\",\n                                      title, seeders)\n                        continue\n\n                    torrent_size = row.find('span', class_='bc torrent-size').get_text().rstrip()\n                    size = convert_size(torrent_size) or -1\n\n                    pubdate_raw = row.find('span', class_='bc cated').get_text(strip=True)\n                    pubdate = self.parse_pubdate(pubdate_raw, human_time=True)\n\n                    item = {\n                        'title': title,\n                        'link': download_url,\n                        'size': size,\n                        'seeders': seeders,\n                        'leechers': leechers,\n                        'pubdate': pubdate,\n                    }\n                    if mode != 'RSS':\n                        log.debug('Found result: {0} with {1} seeders and {2} leechers',\n                                  title, seeders, leechers)\n\n                    items.append(item)\n                except (AttributeError, TypeError, KeyError, ValueError, IndexError):\n                    log.error('Failed parsing provider. Traceback: {0!r}',\n                              traceback.format_exc())\n\n            return items\n\n\nprovider = TorrentProjectProvider()\n", "path": "medusa/providers/torrent/html/torrentproject.py"}]}