alwaysgood commited on
Commit
fba891d
·
verified ·
1 Parent(s): 0d6bf83

Update api_utils.py

Browse files
Files changed (1) hide show
  1. api_utils.py +37 -7
api_utils.py CHANGED
@@ -3,40 +3,70 @@ import pandas as pd
3
  import pytz
4
  import plotly.graph_objects as go
5
  from plotly.subplots import make_subplots
 
6
  from supabase_utils import get_supabase_client
7
  from config import STATION_NAMES
8
 
 
 
 
9
  def fetch_tide_data(station_id, start_utc, end_utc, table='historical_tide'):
10
- """공통 데이터 조회 함수"""
11
  supabase = get_supabase_client()
12
  if not supabase:
 
13
  raise ValueError("Supabase 클라이언트를 생성할 수 없습니다.")
14
 
15
  try:
 
 
 
16
  result = supabase.table(table) \
17
- .select('observed_at, tide_level' if table == 'historical_tide' else 'predicted_at, final_tide_level') \
18
  .eq('station_id', station_id) \
19
- .gte('observed_at' if table == 'historical_tide' else 'predicted_at', start_utc) \
20
- .lte('observed_at' if table == 'historical_tide' else 'predicted_at', end_utc) \
21
- .order('observed_at' if table == 'historical_tide' else 'predicted_at') \
22
  .execute()
 
23
  if not result.data:
24
- raise ValueError(f"데이터가 없습니다: {station_id}, {start_utc} ~ {end_utc}")
 
 
25
  return pd.DataFrame(result.data)
26
  except Exception as e:
 
27
  raise ValueError(f"데이터 조회 오류: {e}")
28
 
29
  def get_tide_data(station_id, start_date=None, end_date=None, include_extremes=False, return_plot=False):
30
- """조위 데이터 조회 및 시각화"""
 
 
 
 
 
 
 
 
 
 
31
  start_date = start_date or datetime.now(pytz.timezone('Asia/Seoul')).strftime('%Y-%m-%d')
32
  start_time = pytz.timezone('Asia/Seoul').localize(datetime.strptime(start_date, '%Y-%m-%d'))
 
 
 
33
  end_time = start_time + timedelta(hours=24) if not end_date else \
34
  pytz.timezone('Asia/Seoul').localize(datetime.strptime(end_date, '%Y-%m-%d')) + timedelta(hours=24)
35
 
 
36
  start_utc = start_time.astimezone(pytz.UTC).isoformat()
37
  end_utc = end_time.astimezone(pytz.UTC).isoformat()
38
 
39
  df = fetch_tide_data(station_id, start_utc, end_utc)
 
 
 
 
40
  df['observed_at'] = pd.to_datetime(df['observed_at']).dt.tz_convert('Asia/Seoul')
41
  df['tide_level'] = pd.to_numeric(df['tide_level'])
42
 
 
3
  import pytz
4
  import plotly.graph_objects as go
5
  from plotly.subplots import make_subplots
6
+ import logging
7
  from supabase_utils import get_supabase_client
8
  from config import STATION_NAMES
9
 
10
+ # Basic logging configuration
11
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
12
+
13
  def fetch_tide_data(station_id, start_utc, end_utc, table='historical_tide'):
14
+ """Fetches data from a specified Supabase table within a date range."""
15
  supabase = get_supabase_client()
16
  if not supabase:
17
+ logging.error("Failed to create a Supabase client.")
18
  raise ValueError("Supabase 클라이언트를 생성할 수 없습니다.")
19
 
20
  try:
21
+ query_column = 'observed_at' if table == 'historical_tide' else 'predicted_at'
22
+ select_columns = 'observed_at, tide_level' if table == 'historical_tide' else 'predicted_at, final_tide_level'
23
+
24
  result = supabase.table(table) \
25
+ .select(select_columns) \
26
  .eq('station_id', station_id) \
27
+ .gte(query_column, start_utc) \
28
+ .lte(query_column, end_utc) \
29
+ .order(query_column) \
30
  .execute()
31
+
32
  if not result.data:
33
+ logging.warning(f"No data found for station {station_id} from {start_utc} to {end_utc} in table '{table}'.")
34
+ return pd.DataFrame() # Return empty DataFrame for robustness
35
+
36
  return pd.DataFrame(result.data)
37
  except Exception as e:
38
+ logging.error(f"Error fetching data for station {station_id}: {e}", exc_info=True)
39
  raise ValueError(f"데이터 조회 오류: {e}")
40
 
41
  def get_tide_data(station_id, start_date=None, end_date=None, include_extremes=False, return_plot=False):
42
+ """
43
+ Retrieves and processes tide data, optionally including tide extremes and a plot.
44
+
45
+ :param station_id: The station identifier.
46
+ :param start_date: Start date in 'YYYY-MM-DD' format. Defaults to today.
47
+ :param end_date: End date in 'YYYY-MM-DD' format. Defaults to the start date.
48
+ :param include_extremes: Whether to calculate and include tidal extremes (high/low tides).
49
+ :param return_plot: Whether to generate and return a Plotly figure.
50
+ :return: A dictionary containing the data, and optionally extremes and a plot.
51
+ """
52
+ # Default to today (in Seoul timezone) if start_date is not provided.
53
  start_date = start_date or datetime.now(pytz.timezone('Asia/Seoul')).strftime('%Y-%m-%d')
54
  start_time = pytz.timezone('Asia/Seoul').localize(datetime.strptime(start_date, '%Y-%m-%d'))
55
+
56
+ # The query period ends 24 hours after the start of the end_date.
57
+ # If no end_date is given, the period is 24 hours from the start_time.
58
  end_time = start_time + timedelta(hours=24) if not end_date else \
59
  pytz.timezone('Asia/Seoul').localize(datetime.strptime(end_date, '%Y-%m-%d')) + timedelta(hours=24)
60
 
61
+ # Convert local time to UTC for the database query.
62
  start_utc = start_time.astimezone(pytz.UTC).isoformat()
63
  end_utc = end_time.astimezone(pytz.UTC).isoformat()
64
 
65
  df = fetch_tide_data(station_id, start_utc, end_utc)
66
+ if df.empty:
67
+ logging.warning(f"No tide data available for station {station_id} for the selected period.")
68
+ return {"data": pd.DataFrame(), "extremes": pd.DataFrame(), "plot": go.Figure()}
69
+
70
  df['observed_at'] = pd.to_datetime(df['observed_at']).dt.tz_convert('Asia/Seoul')
71
  df['tide_level'] = pd.to_numeric(df['tide_level'])
72