Skip to content

Commit 9a37c7f

Browse files
committed
Handle ambiguous timezones so no fallback needed. Also rearrange for cleaner merge
1 parent 3e35ae7 commit 9a37c7f

File tree

1 file changed

+49
-13
lines changed

1 file changed

+49
-13
lines changed

yfinance/base.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@
2222
from __future__ import print_function
2323

2424
import json as _json
25-
import re
2625
import warnings
2726
from io import StringIO
2827
from typing import Optional, Union
2928
from urllib.parse import quote as urlencode
3029

3130
import pandas as pd
32-
import pytz
3331
import requests
3432

3533
from . import utils, cache
@@ -599,20 +597,58 @@ def get_ticker_tz():
599597

600598
# Parse earnings date string
601599
cn = "Earnings Date"
600+
# - remove AM/PM and timezone from date string
601+
tzinfo = dates[cn].str.extract('([AP]M[a-zA-Z]*)$')
602+
dates[cn] = dates[cn].replace(' [AP]M[a-zA-Z]*$', '', regex=True)
603+
# - split AM/PM from timezone
604+
tzinfo = tzinfo[0].str.extract('([AP]M)([a-zA-Z]*)', expand=True)
605+
tzinfo.columns = ["AM/PM", "TZ"]
606+
# - combine and parse
607+
dates[cn] = dates[cn] + ' ' + tzinfo["AM/PM"]
608+
dates[cn] = pd.to_datetime(dates[cn], format="%b %d, %Y, %I %p")
609+
610+
# Try to remap all ambiguous timezone values:
611+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('BST', 'Europe/London')
612+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('GMT', 'Europe/London')
613+
if '.' not in self.ticker:
614+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('EST', 'America/New_York')
615+
elif self.ticker.endswith(".AX"):
616+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('EST', 'Australia/Sydney')
617+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('MST', 'America/Denver')
618+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('PST', 'America/Los_Angeles')
619+
if'.' not in self.ticker:
620+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('CST', 'America/Chicago')
621+
else:
622+
# Revisit if Cuba get a stock exchange
623+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('CST', 'Asia/Shanghai')
624+
if self.ticker.endswith('.TA'):
625+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('IST', 'Asia/Jerusalem')
626+
elif self.ticker.endswith('.IR'):
627+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('IST', 'Europe/Dublin')
628+
elif self.ticker.endswith('.NS'):
629+
tzinfo['TZ'] = tzinfo['TZ'].str.replace('IST', 'Asia/Kolkata')
630+
631+
# But in case still ambiguity that pytz cannot parse, have a backup:
632+
self._quote.proxy = proxy or self.proxy
633+
tz_backup = self._get_ticker_tz(proxy=proxy, timeout=30)
602634

603-
def map_date(time_str: str):
604-
tz_match = re.search('([AP]M)([a-zA-Z]*)$', time_str)
605-
tz_str = tz_match.group(2).strip()
606-
# - remove AM/PM and timezone from date string
607-
time_str = time_str.replace(tz_str, "")
635+
if len(tzinfo['TZ'].unique())==1:
608636
try:
609-
tz = pytz.timezone(tz_str)
610-
except pytz.UnknownTimeZoneError:
611-
tz = get_ticker_tz()
612-
613-
return pd.to_datetime(time_str, format="%b %d, %Y, %I %p").tz_localize(tz)
637+
dates[cn] = dates[cn].dt.tz_localize(tzinfo['TZ'].iloc[0])
638+
except Exception:
639+
dates[cn] = dates[cn].dt.tz_localize(tz_backup)
640+
else:
641+
dates2 = []
642+
for i in range(len(dates)):
643+
dt = dates[cn].iloc[i]
644+
tz = tzinfo['TZ'].iloc[i]
645+
try:
646+
dt = dt.tz_localize(tz)
647+
except Exception:
648+
dt = dt.tz_localize(tz_backup)
649+
dates2.append(dt)
650+
dates[cn] = pd.to_datetime(dates2)
614651

615-
dates[cn] = dates[cn].map(map_date)
616652
dates = dates.set_index("Earnings Date")
617653

618654
self._earnings_dates[limit] = dates

0 commit comments

Comments
 (0)