Skip to content

Commit 24f98d4

Browse files
committed
Standardize on SGT timezone globally
1 parent feccd35 commit 24f98d4

4 files changed

Lines changed: 36 additions & 21 deletions

File tree

main.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
FMP_API_KEY,
2929
TWELVE_DATA_API_KEY,
3030
DATA_DIR,
31+
get_now_sgt,
3132
)
3233
from src.provider_router import ProviderRouter, FilteredStock
3334
from src.gmail_sender import GmailSender
@@ -43,13 +44,13 @@ def wait_for_network(check_interval: int = 300):
4344
"""
4445
print("\n[Network] Checking internet connectivity...")
4546

46-
start_time = datetime.now()
47+
start_time = get_now_sgt()
4748
start_date = start_time.date()
4849
attempt = 0
4950

5051
while True:
5152
attempt += 1
52-
current_time = datetime.now()
53+
current_time = get_now_sgt()
5354
current_date = current_time.date()
5455

5556
# Stop checking if we've moved to the next day
@@ -176,7 +177,7 @@ def mark_day_completed(run_timestamp: datetime, stocks_count: int, email_sent: b
176177
def main():
177178
"""Main entry point."""
178179
args = parse_args()
179-
run_timestamp = datetime.now()
180+
run_timestamp = get_now_sgt()
180181

181182
# Show status if requested
182183
if args.status:

src/cache.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pathlib import Path
1010
from typing import Optional, Dict, Any, List
1111

12-
from .config import CACHE_DB_PATH, PROFILE_CACHE_DAYS
12+
from .config import CACHE_DB_PATH, PROFILE_CACHE_DAYS, get_now_sgt
1313

1414

1515
class ProfileCache:
@@ -56,7 +56,7 @@ def get(self, symbol: str) -> Optional[Dict[str, Any]]:
5656
SELECT * FROM company_profiles
5757
WHERE symbol = ? AND last_updated > ?
5858
""",
59-
(symbol.upper(), datetime.now() - timedelta(days=PROFILE_CACHE_DAYS))
59+
(symbol.upper(), get_now_sgt() - timedelta(days=PROFILE_CACHE_DAYS))
6060
)
6161
row = cursor.fetchone()
6262

@@ -94,7 +94,7 @@ def set(self, symbol: str, profile_data: Dict[str, Any]):
9494
profile_data.get("sector", ""),
9595
profile_data.get("industry", ""),
9696
json.dumps(profile_data),
97-
datetime.now()
97+
get_now_sgt()
9898
)
9999
)
100100
conn.commit()
@@ -140,7 +140,7 @@ def clear_expired(self):
140140
DELETE FROM company_profiles
141141
WHERE last_updated < ?
142142
""",
143-
(datetime.now() - timedelta(days=PROFILE_CACHE_DAYS),)
143+
(get_now_sgt() - timedelta(days=PROFILE_CACHE_DAYS),)
144144
)
145145
conn.commit()
146146

@@ -155,7 +155,7 @@ def stats(self) -> Dict[str, Any]:
155155
SELECT COUNT(*) FROM company_profiles
156156
WHERE last_updated > ?
157157
""",
158-
(datetime.now() - timedelta(days=PROFILE_CACHE_DAYS),)
158+
(get_now_sgt() - timedelta(days=PROFILE_CACHE_DAYS),)
159159
)
160160
valid = cursor.fetchone()[0]
161161

src/config.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,22 @@
66
import os
77
import time
88
import datetime
9+
import pytz
910
from pathlib import Path
1011
from dotenv import load_dotenv
1112

12-
# Set timezone to Singapore
13+
# Set timezone to Singapore (SGT)
14+
SGT = pytz.timezone('Asia/Singapore')
1315
os.environ['TZ'] = 'Asia/Singapore'
14-
time.tzset()
16+
try:
17+
time.tzset()
18+
except AttributeError:
19+
# tzset only works on Unix
20+
pass
21+
22+
def get_now_sgt():
23+
"""Get current time in Singapore Timezone."""
24+
return datetime.datetime.now(SGT)
1525

1626
# Load .env file from project root
1727
PROJECT_ROOT = Path(__file__).parent.parent

src/credit_tracker.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
from threading import Lock
1212

1313
from .config import (
14-
CREDIT_TRACKER_PATH,
1514
TWELVE_DATA_DAILY_LIMIT,
16-
TWELVE_DATA_MINUTE_LIMIT
15+
TWELVE_DATA_MINUTE_LIMIT,
16+
SGT,
17+
get_now_sgt,
1718
)
1819

1920

@@ -39,9 +40,10 @@ def _load_state(self):
3940
self._last_date = state.get("last_date", "")
4041

4142
# Reset if it's a new day
42-
if self._last_date != str(date.today()):
43+
today_sgt = str(get_now_sgt().date())
44+
if self._last_date != today_sgt:
4345
self._daily_credits = 0
44-
self._last_date = str(date.today())
46+
self._last_date = today_sgt
4547
except (json.JSONDecodeError, KeyError):
4648
self._reset_state()
4749
else:
@@ -50,7 +52,7 @@ def _load_state(self):
5052
def _reset_state(self):
5153
"""Reset to initial state."""
5254
self._daily_credits = 0
53-
self._last_date = str(date.today())
55+
self._last_date = str(get_now_sgt().date())
5456
self._save_state()
5557

5658
def _save_state(self):
@@ -59,17 +61,18 @@ def _save_state(self):
5961
json.dump({
6062
"daily_credits": self._daily_credits,
6163
"last_date": self._last_date,
62-
"last_updated": datetime.now().isoformat()
64+
"last_updated": get_now_sgt().isoformat()
6365
}, f, indent=2)
6466

6567
@property
6668
def daily_credits_used(self) -> int:
6769
"""Get the number of credits used today."""
6870
with self._lock:
6971
# Check if we need to reset for a new day
70-
if self._last_date != str(date.today()):
72+
today_sgt = str(get_now_sgt().date())
73+
if self._last_date != today_sgt:
7174
self._daily_credits = 0
72-
self._last_date = str(date.today())
75+
self._last_date = today_sgt
7376
self._save_state()
7477
return self._daily_credits
7578

@@ -111,9 +114,10 @@ def record_usage(self, credits: int = 1):
111114
"""
112115
with self._lock:
113116
# Check for day rollover
114-
if self._last_date != str(date.today()):
117+
today_sgt = str(get_now_sgt().date())
118+
if self._last_date != today_sgt:
115119
self._daily_credits = 0
116-
self._last_date = str(date.today())
120+
self._last_date = today_sgt
117121

118122
self._daily_credits += credits
119123
self._minute_calls.append(time.time())
@@ -143,7 +147,7 @@ def get_status(self) -> Dict[str, Any]:
143147
"daily_limit": TWELVE_DATA_DAILY_LIMIT,
144148
"minute_remaining": self.minute_credits_remaining,
145149
"minute_limit": TWELVE_DATA_MINUTE_LIMIT,
146-
"date": str(date.today())
150+
"date": str(get_now_sgt().date())
147151
}
148152

149153
def throttle_if_needed(self, credits_needed: int = 1) -> bool:

0 commit comments

Comments
 (0)