# Buggy code
def parse_pubdate(pubdate, human_time=False, timezone=None, **kwargs):
    """
    Parse publishing date into a datetime object.

    :param pubdate: date and time string
    :param human_time: string uses human slang ("4 hours ago")
    :param timezone: use a different timezone ("US/Eastern")

    :keyword dayfirst: Interpret the first value as the day
    :keyword yearfirst: Interpret the first value as the year

    :returns: a datetime object or None
    """
    now_alias = ("right now", "just now", "now")

    df = kwargs.pop("dayfirst", False)
    yf = kwargs.pop("yearfirst", False)
    fromtimestamp = kwargs.pop("fromtimestamp", False)

    # This can happen from time to time
    if pubdate is None:
        log.debug("Skipping invalid publishing date.")
        return

    try:
        if human_time:
            if pubdate.lower() in now_alias:
                seconds = 0
            else:
                match = re.search(r"(?P<time>[\d.]+\W*)(?P<granularity>\w+)", pubdate)
                matched_time = match.group("time")
                matched_granularity = match.group("granularity")

                # The parse method does not support decimals used with the month,
                # months, year or years granularities.
                if matched_granularity and matched_granularity in (
                    "month",
                    "months",
                    "year",
                    "years",
                ):
                    matched_time = int(round(float(matched_time.strip())))

                seconds = parse("{0} {1}".format(matched_time, matched_granularity))
            return datetime.now(tz.tzlocal()) - timedelta(seconds=seconds)

        if fromtimestamp:
            dt = datetime.fromtimestamp(int(pubdate), tz=tz.gettz("UTC"))
        else:
            dt = parser.parse(pubdate, dayfirst=df, yearfirst=yf, fuzzy=True)

        # Always make UTC aware if naive
        if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
            dt = dt.replace(tzinfo=tz.gettz("UTC"))
        if timezone:
            dt = dt.astimezone(tz.gettz(timezone))

        return dt
    except (AttributeError, TypeError, ValueError):
        log.exception("Failed parsing publishing date: {0}", pubdate)


# Traceback (ValueError)
2018-09-01 09:52:38 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Evil Genius
2018-09-01 09:52:38 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.000/3.000]. Keeping it: [cyberwar.s02e02.1080p.web.x264-tbs.mkv]
2018-09-01 09:52:38 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from The Mask: The Animated Series
2018-09-01 09:52:38 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from London Spy
2018-09-01 09:52:38 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from SciJinks
2018-09-01 09:52:38 INFO     TORRENTCHECKER :: [d7da594] Torrent not yet post-processed. Skipping: Rick.and.Morty.S03E07.720p.HDTV.x264-BATV
2018-09-01 09:52:38 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Rabbids Invasion
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Wyatt Cenac's Problem Areas
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from O Negócio
2018-09-01 09:52:39 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.377/1.500]. Keeping it: [A.Series.of.Unfortunate.Events.S02E06.1080p.WEB.x264-METCON]
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Explained
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Condor
2018-09-01 09:52:39 INFO     TORRENTCHECKER :: [d7da594] Torrent completed and reached minimum ratio but it was force started again. Current ratio: [0.153/0.000]. Keeping it: [hack.my.life.s04e02.720p.webrip.x264-tbs.mkv]
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Marvel's Cloak & Dagger
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Hunting ISIS
2018-09-01 09:52:39 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Cults and Extreme Belief
2018-09-01 09:52:40 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.000/6.000]. Keeping it: [American.Pickers.S19E08.720p.WEB.h264-TBS]
2018-09-01 09:52:40 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from House Hunters
2018-09-01 09:52:40 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Famous Food Truck
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Ghosted
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Nathan For You
2018-09-01 09:52:41 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.570/6.000]. Keeping it: [Adventure.Time.S09E17.720p.HDTV.x264-W4F]
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Britain's Secret Charity Cheats
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Disenchantment
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Eight Go Rallying: The Road to Saigon
2018-09-01 09:52:41 INFO     TORRENTCHECKER :: [d7da594] Torrent not yet post-processed. Skipping: Chefs.Table.S04E04.720p.WEBRip.x264-SKGTV
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Unforgotten
2018-09-01 09:52:41 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Who Is America?
2018-09-01 09:52:42 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [1.551/2.000]. Keeping it: [Robot.Chicken.S09E15.720p.HDTV.x264-BATV[xsn]]
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from SEAL Team
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Seeing if we need anything from Tom Clancy’s Jack Ryan
2018-09-01 09:52:42 INFO     SEARCHQUEUE-DAILY-SEARCH :: [d7da594] Using daily search providers
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Updating providers cache
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] GET URL: https://usenet-crawler.com/api?apikey=**********&t=caps [Status: 503]
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] User-Agent: Medusa/0.2.8 (Linux; 4.9.35-v7+; f6ef9754-ad2c-11e8-9684-b827eb6b4d4c)
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] The response returned a non-200 response while requesting url https://usenet-crawler.com/api Error: HTTPError(u'503 Server Error: Service Unavailable for url: https://usenet-crawler.com/api?apikey=**********&t=caps',)
2018-09-01 09:52:42 WARNING  SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Error getting caps xml for: Usenet-Crawler
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Search mode: RSS
2018-09-01 09:52:42 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.197/1.500]. Keeping it: [Cops.S31E05.1080p.WEB.x264-TBS]
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] GET URL: https://usenet-crawler.com/api?apikey=**********&maxage=3331&cat=5000%2C5080%2C5020%2C5040%2C5050%2C5030%2C5060&limit=100&t=search&offset=0 [Status: 503]
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] User-Agent: Medusa/0.2.8 (Linux; 4.9.35-v7+; f6ef9754-ad2c-11e8-9684-b827eb6b4d4c)
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] The response returned a non-200 response while requesting url https://usenet-crawler.com/api Error: HTTPError(u'503 Server Error: Service Unavailable for url: https://usenet-crawler.com/api?apikey=**********&maxage=3331&cat=5000%2C5080%2C5020%2C5040%2C5050%2C5030%2C5060&limit=100&t=search&offset=0',)
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] No data returned from provider
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] GET URL: https://usenet-crawler.com/api?apikey=**********&t=caps [Status: 503]
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] User-Agent: Medusa/0.2.8 (Linux; 4.9.35-v7+; f6ef9754-ad2c-11e8-9684-b827eb6b4d4c)
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] The response returned a non-200 response while requesting url https://usenet-crawler.com/api Error: HTTPError(u'503 Server Error: Service Unavailable for url: https://usenet-crawler.com/api?apikey=**********&t=caps',)
2018-09-01 09:52:42 WARNING  SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Error getting caps xml for: Usenet-Crawler
2018-09-01 09:52:42 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Search mode: RSS
2018-09-01 09:52:43 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] GET URL: https://usenet-crawler.com/api?apikey=**********&maxage=3331&cat=5000%2C5080%2C5020%2C5040%2C5050%2C5030%2C5060&limit=100&t=search&offset=0 [Status: 503]
2018-09-01 09:52:43 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] User-Agent: Medusa/0.2.8 (Linux; 4.9.35-v7+; f6ef9754-ad2c-11e8-9684-b827eb6b4d4c)
2018-09-01 09:52:43 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] The response returned a non-200 response while requesting url https://usenet-crawler.com/api Error: HTTPError(u'503 Server Error: Service Unavailable for url: https://usenet-crawler.com/api?apikey=**********&maxage=3331&cat=5000%2C5080%2C5020%2C5040%2C5050%2C5030%2C5060&limit=100&t=search&offset=0',)
2018-09-01 09:52:43 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] No data returned from provider
2018-09-01 09:52:43 INFO     SEARCHQUEUE-DAILY-SEARCH :: [Usenet-Crawler] :: [d7da594] Removing cache entries older than 15 days from usenet_crawler
2018-09-01 09:52:43 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [1.290/4.000]. Keeping it: [Family.Guy.S16E04.1080p.WEB.x264-TBS]
2018-09-01 09:52:43 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.003/4.000]. Keeping it: [Patagonia.Earths.Secret.Paradise.2015.1080i.HDTV.H.264.DD2.0-Irishman]
2018-09-01 09:52:43 INFO     TORRENTCHECKER :: [d7da594] Torrent completed and reached minimum ratio but it was force started again. Current ratio: [0.758/0.000]. Keeping it: [running.wild.with.bear.grylls.s03e08.720p.hdtv.x264-w4f.mkv]
2018-09-01 09:52:44 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Updating providers cache
2018-09-01 09:52:44 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Search mode: RSS
2018-09-01 09:52:44 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.000/2.000]. Keeping it: [Hunting.Nazi.Treasure.S01E07.Blood.Treasure.WEBRip.x264-CAFFEiNE]
2018-09-01 09:52:44 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.000/4.000]. Keeping it: [cyberwar.s01e13.720p.hdtv.x264-w4f.mkv]
2018-09-01 09:52:45 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [0.079/2.000]. Keeping it: [3.Percent.S02E01.1080p.WEB.x264-SKGTV]
2018-09-01 09:52:45 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] GET URL: https://hd-space.org/index.php?active=0&category=15%3B40%3B21%3B22%3B24%3B25%3B27%3B28&search=&page=torrents&options=0 [Status: 200]
2018-09-01 09:52:45 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] User-Agent: Medusa/0.2.8 (Linux; 4.9.35-v7+; f6ef9754-ad2c-11e8-9684-b827eb6b4d4c)
2018-09-01 09:52:45 INFO     TORRENTCHECKER :: [d7da594] Torrent did not reach minimum ratio: [1.103/1.500]. Keeping it: [Evil.Genius.The.True.Story.of.Americas.Most.Diabolical.Bank.Heist.S01E04.1080p.WEB.x264-STRiFE]
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Ducktales 2017 S01 1080p AMZN WEB DL DDP2 0 H 264 TVSmash with 1 seeders and 6 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: The Walking Dead Complete season 7 x264 , MKV , 1080p   {iMIKEY84} with 1 seeders and 2 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: '71 2014 1080p Blu-ray AVC DTS-HD MA 5.1-F13@HDSpace with 48 seeders and 3 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Somebody.Feed.Phil.S01.1080p.NF.WEB-DL.DD5.1.H.264-MZABI with 2 seeders and 0 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Oceans.Eight.2018.BluRay.1080p.TrueHD.Atmos.7.1.AVC.REMUX-FraMeSToR  with 15 seeders and 1 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Inside the Criminal Mind S01 1080p WEB-DL DD+2.0 H.264-MZABI with 3 seeders and 0 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Tom Clancy's Jack Ryan S01 1080p AMZN WEB-DL DDP5 1 H264 NTG with 29 seeders and 4 leechers
2018-09-01 09:52:46 INFO     TORRENTCHECKER :: [d7da594] Torrent completed and reached minimum ratio but it was force started again. Current ratio: [0.041/0.000]. Keeping it: [the.gadget.show.s29e04.1080p.hdtv.x264-qpel.mkv]
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Hereditary 2018 1080p BluRay AVC DTS-HD MA 5.1-CHDBits with 7 seeders and 0 leechers
2018-09-01 09:52:46 DEBUG    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Found result: Ocean's Eight 2018 1080p BluRay AVC Atmos-CHDBits with 16 seeders and 1 leechers
2018-09-01 09:52:46 ERROR    SEARCHQUEUE-DAILY-SEARCH :: [HDSpace] :: [d7da594] Failed parsing publishing date: Yesterday at Today at 
Traceback (most recent call last):
  File "/home/pi/Medusa/medusa/providers/generic_provider.py", line 582, in parse_pubdate
    dt = parser.parse(pubdate, dayfirst=df, yearfirst=yf, fuzzy=True)
  File "/home/pi/Medusa/ext/dateutil/parser/_parser.py", line 1356, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/home/pi/Medusa/ext/dateutil/parser/_parser.py", line 651, in parse
    raise ValueError("String does not contain a date:", timestr)
ValueError: (u'String does not contain a date:', u'Yesterday at\xa0Today at\xa0')

# Fixed code
def parse_pubdate(pubdate, human_time=False, timezone=None, **kwargs):
    """
    Parse publishing date into a datetime object.

    :param pubdate: date and time string
    :param human_time: string uses human slang ("4 hours ago")
    :param timezone: use a different timezone ("US/Eastern")

    :keyword dayfirst: Interpret the first value as the day
    :keyword yearfirst: Interpret the first value as the year

    :returns: a datetime object or None
    """
    now_alias = ("right now", "just now", "now")

    df = kwargs.pop("dayfirst", False)
    yf = kwargs.pop("yearfirst", False)
    fromtimestamp = kwargs.pop("fromtimestamp", False)

    # This can happen from time to time
    if pubdate is None:
        log.debug("Skipping invalid publishing date.")
        return

    try:
        if human_time:
            if pubdate.lower() in now_alias:
                seconds = 0
            else:
                match = re.search(r"(?P<time>[\d.]+\W*)(?P<granularity>\w+)", pubdate)
                matched_time = match.group("time")
                matched_granularity = match.group("granularity")

                # The parse method does not support decimals used with the month,
                # months, year or years granularities.
                if matched_granularity and matched_granularity in (
                    "month",
                    "months",
                    "year",
                    "years",
                ):
                    matched_time = int(round(float(matched_time.strip())))

                seconds = parse("{0} {1}".format(matched_time, matched_granularity))
                if seconds is None:
                    log.warning(
                        "Failed parsing human time: {0} {1}",
                        matched_time,
                        matched_granularity,
                    )
                    raise ValueError(
                        "Failed parsing human time: {0} {1}".format(
                            matched_time, matched_granularity
                        )
                    )

            return datetime.now(tz.tzlocal()) - timedelta(seconds=seconds)

        if fromtimestamp:
            dt = datetime.fromtimestamp(int(pubdate), tz=tz.gettz("UTC"))
        else:
            day_offset = 0
            if "yesterday at" in pubdate.lower() or "today at" in pubdate.lower():
                # Extract a time
                time = re.search(r"(?P<time>[0-9:]+)", pubdate)
                if time:
                    if "yesterday" in pubdate:
                        day_offset = 1
                    pubdate = time.group("time").strip()

            dt = parser.parse(
                pubdate, dayfirst=df, yearfirst=yf, fuzzy=True
            ) - timedelta(days=day_offset)

        # Always make UTC aware if naive
        if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None:
            dt = dt.replace(tzinfo=tz.gettz("UTC"))
        if timezone:
            dt = dt.astimezone(tz.gettz(timezone))

        return dt
    except (AttributeError, TypeError, ValueError):
        log.exception("Failed parsing publishing date: {0}", pubdate)