display time in current TZ

This commit is contained in:
Dobromir Popov 2025-03-25 11:18:36 +02:00
parent 058816ddcd
commit 05f61b5663

View File

@ -17,6 +17,8 @@ from threading import Thread
import requests
import os
from datetime import datetime, timedelta
import pytz
import tzlocal
# Configure logging with more detailed format
logging.basicConfig(
@ -29,6 +31,50 @@ logging.basicConfig(
)
logger = logging.getLogger(__name__)
# Try to get local timezone, default to Sofia/EET if not available
try:
local_timezone = tzlocal.get_localzone()
# Get timezone name safely
try:
tz_name = str(local_timezone)
# Handle case where it might be zoneinfo.ZoneInfo object instead of pytz timezone
if hasattr(local_timezone, 'zone'):
tz_name = local_timezone.zone
elif hasattr(local_timezone, 'key'):
tz_name = local_timezone.key
else:
tz_name = str(local_timezone)
except:
tz_name = "Local"
logger.info(f"Detected local timezone: {local_timezone} ({tz_name})")
except Exception as e:
logger.warning(f"Could not detect local timezone: {str(e)}. Defaulting to Sofia/EET")
local_timezone = pytz.timezone('Europe/Sofia')
tz_name = "Europe/Sofia"
def convert_to_local_time(timestamp):
"""Convert timestamp to local timezone"""
try:
if isinstance(timestamp, pd.Timestamp):
dt = timestamp.to_pydatetime()
elif isinstance(timestamp, np.datetime64):
dt = pd.Timestamp(timestamp).to_pydatetime()
elif isinstance(timestamp, str):
dt = pd.to_datetime(timestamp).to_pydatetime()
else:
dt = timestamp
# If datetime is naive (no timezone), assume it's UTC
if dt.tzinfo is None:
dt = dt.replace(tzinfo=pytz.UTC)
# Convert to local timezone
local_dt = dt.astimezone(local_timezone)
return local_dt
except Exception as e:
logger.error(f"Error converting timestamp to local time: {str(e)}")
return timestamp
class TradeTickStorage:
"""Store and manage raw trade ticks for display and candle formation"""
def __init__(self, max_age_seconds: int = 1800): # 30 minutes by default
@ -1110,10 +1156,19 @@ class RealTimeChart:
logger.debug(f"Displaying {len(display_df)} candles in main chart")
# Convert timestamps to local time for display
display_df = display_df.copy()
try:
display_df['local_time'] = display_df['timestamp'].apply(convert_to_local_time)
logger.debug(f"Converted timestamps to local time ({local_timezone})")
except Exception as e:
logger.error(f"Error converting timestamps to local time: {str(e)}")
display_df['local_time'] = display_df['timestamp']
# Add candlestick chart
fig.add_trace(
go.Candlestick(
x=display_df['timestamp'],
x=display_df['local_time'], # Use local time for display
open=display_df['open'],
high=display_df['high'],
low=display_df['low'],
@ -1131,7 +1186,7 @@ class RealTimeChart:
fig.add_trace(
go.Bar(
x=display_df['timestamp'],
x=display_df['local_time'], # Use local time for display
y=display_df['volume'],
name='Volume',
marker_color=colors
@ -1141,21 +1196,30 @@ class RealTimeChart:
# Add latest price line from the candlestick data
latest_price = display_df['close'].iloc[-1]
latest_time = display_df['local_time'].iloc[-1]
earliest_time = display_df['local_time'].iloc[0]
fig.add_shape(
type="line",
x0=display_df['timestamp'].min(),
x0=earliest_time,
y0=latest_price,
x1=display_df['timestamp'].max(),
x1=latest_time,
y1=latest_price,
line=dict(color="yellow", width=1, dash="dash"),
row=1, col=1
)
# Format the last update time in local timezone
try:
last_update_time = latest_time.strftime('%Y-%m-%d %H:%M:%S')
except:
last_update_time = datetime.now().astimezone(local_timezone).strftime('%Y-%m-%d %H:%M:%S')
# Annotation for last candle close price
fig.add_annotation(
x=display_df['timestamp'].max(),
x=latest_time,
y=latest_price,
text=f"{latest_price:.2f}",
text=f"{latest_price:.2f} ({last_update_time})",
showarrow=False,
font=dict(size=14, color="yellow"),
xshift=50,
@ -1167,19 +1231,22 @@ class RealTimeChart:
# Add current price line
fig.add_shape(
type="line",
x0=display_df['timestamp'].min(),
x0=earliest_time,
y0=current_price,
x1=display_df['timestamp'].max(),
x1=latest_time,
y1=current_price,
line=dict(color="cyan", width=1, dash="dot"),
row=1, col=1
)
# Format current time in local timezone
current_time_str = datetime.now().astimezone(local_timezone).strftime('%Y-%m-%d %H:%M:%S')
# Add current price annotation
fig.add_annotation(
x=display_df['timestamp'].max(),
x=latest_time,
y=current_price,
text=f"Current: {current_price:.2f}",
text=f"Current: {current_price:.2f} ({current_time_str})",
showarrow=False,
font=dict(size=14, color="cyan"),
xshift=50,
@ -1221,13 +1288,21 @@ class RealTimeChart:
if len(ohlcv_df) > 100:
ohlcv_df = ohlcv_df.tail(100)
# Convert to local time
ohlcv_display_df = ohlcv_df.copy()
try:
ohlcv_display_df['local_time'] = ohlcv_df['timestamp'].apply(convert_to_local_time)
except Exception as e:
logger.error(f"Error converting {interval_key} timestamps to local time: {str(e)}")
ohlcv_display_df['local_time'] = ohlcv_df['timestamp']
fig.add_trace(
go.Candlestick(
x=ohlcv_df['timestamp'],
open=ohlcv_df['open'],
high=ohlcv_df['high'],
low=ohlcv_df['low'],
close=ohlcv_df['close'],
x=ohlcv_display_df['local_time'],
open=ohlcv_display_df['open'],
high=ohlcv_display_df['high'],
low=ohlcv_display_df['low'],
close=ohlcv_display_df['close'],
name=f'{label}',
increasing_line_color='#33CC33',
decreasing_line_color='#FF4136',
@ -1237,23 +1312,33 @@ class RealTimeChart:
)
# Add latest price line
latest_timeframe_price = ohlcv_df['close'].iloc[-1] if len(ohlcv_df) > 0 else None
latest_timeframe_price = ohlcv_display_df['close'].iloc[-1] if len(ohlcv_display_df) > 0 else None
if latest_timeframe_price:
# Get first and last timestamps
earliest_tf_time = ohlcv_display_df['local_time'].iloc[0]
latest_tf_time = ohlcv_display_df['local_time'].iloc[-1]
fig.add_shape(
type="line",
x0=ohlcv_df['timestamp'].min(),
x0=earliest_tf_time,
y0=latest_timeframe_price,
x1=ohlcv_df['timestamp'].max(),
x1=latest_tf_time,
y1=latest_timeframe_price,
line=dict(color="yellow", width=1, dash="dash"),
row=row_idx, col=1
)
# Get formatted time
try:
update_time = latest_tf_time.strftime('%Y-%m-%d %H:%M')
except:
update_time = ""
# Add price annotation
fig.add_annotation(
x=ohlcv_df['timestamp'].max(),
x=latest_tf_time,
y=latest_timeframe_price,
text=f"{latest_timeframe_price:.2f}",
text=f"{latest_timeframe_price:.2f} ({update_time})",
showarrow=False,
font=dict(size=12, color="yellow"),
xshift=50,
@ -1279,13 +1364,21 @@ class RealTimeChart:
if len(ohlcv_df) > 100:
ohlcv_df = ohlcv_df.tail(100)
# Convert to local time
ohlcv_display_df = ohlcv_df.copy()
try:
ohlcv_display_df['local_time'] = ohlcv_df['timestamp'].apply(convert_to_local_time)
except Exception as e:
logger.error(f"Error converting {interval_key} timestamps to local time: {str(e)}")
ohlcv_display_df['local_time'] = ohlcv_df['timestamp']
fig.add_trace(
go.Candlestick(
x=ohlcv_df['timestamp'],
open=ohlcv_df['open'],
high=ohlcv_df['high'],
low=ohlcv_df['low'],
close=ohlcv_df['close'],
x=ohlcv_display_df['local_time'],
open=ohlcv_display_df['open'],
high=ohlcv_display_df['high'],
low=ohlcv_display_df['low'],
close=ohlcv_display_df['close'],
name=f'{label}',
increasing_line_color='#33CC33',
decreasing_line_color='#FF4136',
@ -1293,6 +1386,40 @@ class RealTimeChart:
),
row=row_idx, col=1
)
# Add latest price line
latest_timeframe_price = ohlcv_display_df['close'].iloc[-1] if len(ohlcv_display_df) > 0 else None
if latest_timeframe_price:
# Get first and last timestamps
earliest_tf_time = ohlcv_display_df['local_time'].iloc[0]
latest_tf_time = ohlcv_display_df['local_time'].iloc[-1]
fig.add_shape(
type="line",
x0=earliest_tf_time,
y0=latest_timeframe_price,
x1=latest_tf_time,
y1=latest_timeframe_price,
line=dict(color="yellow", width=1, dash="dash"),
row=row_idx, col=1
)
# Get formatted time
try:
update_time = latest_tf_time.strftime('%Y-%m-%d %H:%M')
except:
update_time = ""
# Add price annotation
fig.add_annotation(
x=latest_tf_time,
y=latest_timeframe_price,
text=f"{latest_timeframe_price:.2f} ({update_time})",
showarrow=False,
font=dict(size=12, color="yellow"),
xshift=50,
row=row_idx, col=1
)
# Add a message to the empty main chart
fig.add_annotation(
@ -1317,6 +1444,10 @@ class RealTimeChart:
# Build info box text with all the statistics
info_lines = [f"<b>{self.symbol}</b>"]
# Add current time in local timezone
current_local_time = datetime.now().astimezone(local_timezone)
info_lines.append(f"Time: {current_local_time.strftime('%Y-%m-%d %H:%M:%S')} ({tz_name})")
# Add current price if available
if current_price:
info_lines.append(f"Current: <b>{current_price:.2f}</b> USDT")