Use timezone-aware timestamps and update tests

This commit is contained in:
Alexa Amundson
2025-11-16 06:41:33 -06:00
parent 44f928d88e
commit a0f26b8ebc
29 changed files with 110 additions and 71 deletions

View File

@@ -10,6 +10,7 @@ from app.database import get_db
from app.models.user import User
from app.models.ai_chat import Conversation, Message, MessageRole
from app.auth import get_current_active_user
from app.utils import utc_now
router = APIRouter(prefix="/api/ai-chat", tags=["AI Chat"])
@@ -188,7 +189,7 @@ async def send_message(
# Update conversation
conversation.message_count += 2
conversation.updated_at = datetime.utcnow()
conversation.updated_at = utc_now()
if not conversation.title or conversation.title == "New Conversation":
# Auto-generate title from first message

View File

@@ -13,6 +13,8 @@ import asyncio
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/health", tags=["health"])
@@ -47,7 +49,7 @@ async def check_api_status(name: str, check_func) -> Dict[str, Any]:
"name": name,
"status": "connected" if result.get("connected") else "not_configured",
"message": result.get("message", ""),
"last_checked": datetime.utcnow().isoformat(),
"last_checked": utc_now().isoformat(),
"configuration": {
k: v for k, v in result.items()
if k.endswith("_configured") or k == "connected"
@@ -60,7 +62,7 @@ async def check_api_status(name: str, check_func) -> Dict[str, Any]:
"name": name,
"status": "error",
"message": f"Health check failed: {str(e)}",
"last_checked": datetime.utcnow().isoformat(),
"last_checked": utc_now().isoformat(),
"configuration": {},
"error": str(e)
}
@@ -154,7 +156,7 @@ async def check_all_apis():
return SystemHealthStatus(
status=overall_status,
timestamp=datetime.utcnow().isoformat(),
timestamp=utc_now().isoformat(),
total_apis=total_apis,
connected_apis=connected_count,
not_configured_apis=not_configured_count,

View File

@@ -17,7 +17,7 @@ from app.auth import (
)
from app.services.blockchain import BlockchainService
from app.services.crypto import wallet_crypto, WalletKeyEncryptionError
from datetime import datetime
from app.utils import utc_now
router = APIRouter(prefix="/api/auth", tags=["Authentication"])
@@ -82,7 +82,7 @@ async def register(user_data: UserCreate, db: AsyncSession = Depends(get_db)):
wallet_address=wallet_address,
wallet_private_key=encrypted_private_key,
balance=100.0, # Starting bonus
created_at=datetime.utcnow()
created_at=utc_now()
)
db.add(user)
@@ -131,7 +131,7 @@ async def login(
)
# Update last login
user.last_login = datetime.utcnow()
user.last_login = utc_now()
await db.commit()
# Create tokens

View File

@@ -12,7 +12,6 @@ from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import List, Optional
from datetime import datetime
import httpx
from urllib.parse import urlparse, quote
import hashlib
@@ -21,6 +20,7 @@ from ..database import get_db
from ..auth import get_current_user
from ..models import User
from pydantic import BaseModel, HttpUrl
from ..utils import utc_now
router = APIRouter(prefix="/api/browser", tags=["browser"])
@@ -142,7 +142,7 @@ async def add_bookmark(
"title": bookmark.title,
"url": bookmark.url,
"folder": bookmark.folder,
"created_at": datetime.utcnow().isoformat()
"created_at": utc_now().isoformat()
}
return {
@@ -208,10 +208,10 @@ async def add_history_entry(
):
"""Add a history entry"""
new_entry = {
"id": hashlib.md5(f"{entry.url}{datetime.utcnow()}".encode()).hexdigest()[:8],
"id": hashlib.md5(f"{entry.url}{utc_now()}".encode()).hexdigest()[:8],
"url": entry.url,
"title": entry.title,
"visited_at": datetime.utcnow().isoformat()
"visited_at": utc_now().isoformat()
}
return {
@@ -232,7 +232,7 @@ async def clear_history(
@router.get("/search")
async def web_search(
q: str = Query(..., min_length=1, description="Search query"),
engine: str = Query("duckduckgo", regex="^(duckduckgo|google|bing)$"),
engine: str = Query("duckduckgo", pattern="^(duckduckgo|google|bing)$"),
current_user: User = Depends(get_current_user)
):
"""
@@ -397,7 +397,7 @@ async def open_new_tab(
"""Open a new tab"""
return {
"tab": {
"id": hashlib.md5(f"{url}{datetime.utcnow()}".encode()).hexdigest()[:8],
"id": hashlib.md5(f"{url}{utc_now()}".encode()).hexdigest()[:8],
"url": url,
"title": "Loading...",
"active": True

View File

@@ -19,6 +19,7 @@ from ..database import get_db
from ..auth import get_current_user
from ..models import User, Device, Email, Post, Video, File, Conversation, Block, Transaction
from pydantic import BaseModel
from ..utils import utc_now
router = APIRouter(prefix="/api/dashboard", tags=["dashboard"])
@@ -201,7 +202,7 @@ async def get_dashboard_overview(
},
"services": services,
"system_health": system_health,
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}
@@ -356,7 +357,7 @@ async def get_recent_activity(
"icon": "📧",
"action": "Received new email",
"description": "Meeting reminder from Sarah",
"timestamp": (datetime.utcnow() - timedelta(minutes=5)).isoformat()
"timestamp": (utc_now() - timedelta(minutes=5)).isoformat()
},
{
"id": 2,
@@ -364,7 +365,7 @@ async def get_recent_activity(
"icon": "⛓️",
"action": "Transaction completed",
"description": "Sent 10 RoadCoins to wallet abc123",
"timestamp": (datetime.utcnow() - timedelta(minutes=15)).isoformat()
"timestamp": (utc_now() - timedelta(minutes=15)).isoformat()
},
{
"id": 3,
@@ -372,7 +373,7 @@ async def get_recent_activity(
"icon": "⛏️",
"action": "Block mined",
"description": "Mined block #1234, earned 50 RoadCoins",
"timestamp": (datetime.utcnow() - timedelta(hours=1)).isoformat()
"timestamp": (utc_now() - timedelta(hours=1)).isoformat()
},
{
"id": 4,
@@ -380,7 +381,7 @@ async def get_recent_activity(
"icon": "🥧",
"action": "Device connected",
"description": "Raspberry Pi 4 - Living Room came online",
"timestamp": (datetime.utcnow() - timedelta(hours=2)).isoformat()
"timestamp": (utc_now() - timedelta(hours=2)).isoformat()
},
{
"id": 5,
@@ -388,7 +389,7 @@ async def get_recent_activity(
"icon": "🌐",
"action": "New like",
"description": "Mike liked your post",
"timestamp": (datetime.utcnow() - timedelta(hours=3)).isoformat()
"timestamp": (utc_now() - timedelta(hours=3)).isoformat()
}
]

View File

@@ -10,6 +10,7 @@ from app.database import get_db
from app.models.device import Device, DeviceMetric, DeviceLog
from app.models.user import User
from app.routers.auth import get_current_user
from app.utils import utc_now
router = APIRouter(prefix="/api/devices", tags=["devices"])
@@ -239,7 +240,7 @@ async def update_device(
if device_data.description is not None:
device.description = device_data.description
device.updated_at = datetime.utcnow()
device.updated_at = utc_now()
await db.commit()
await db.refresh(device)
@@ -265,7 +266,7 @@ async def device_heartbeat(
# Update device status
device.is_online = True
device.status = "online"
device.last_seen = datetime.utcnow()
device.last_seen = utc_now()
# Update system info if provided
if heartbeat_data.ip_address:
@@ -308,7 +309,7 @@ async def device_heartbeat(
# Save metric snapshot
metric = DeviceMetric(
device_id=device.id,
timestamp=datetime.utcnow(),
timestamp=utc_now(),
cpu_usage=heartbeat_data.cpu_usage_percent,
ram_usage=heartbeat_data.ram_usage_percent,
disk_usage=heartbeat_data.disk_usage_percent,
@@ -392,7 +393,7 @@ async def ssh_connect(
"device_id": device_id,
"ip_address": device.ip_address,
"hostname": device.hostname,
"connection_token": f"ssh_token_{device_id}_{datetime.utcnow().timestamp()}",
"connection_token": f"ssh_token_{device_id}_{utc_now().timestamp()}",
"status": "connected",
"message": f"SSH connection established to {device.hostname or device.ip_address}"
}
@@ -448,7 +449,7 @@ async def ssh_execute_command(
"command": command_data.command,
"output": output,
"exit_code": 0,
"executed_at": datetime.utcnow().isoformat()
"executed_at": utc_now().isoformat()
}
@@ -511,7 +512,7 @@ async def deploy_to_device(
"deploy_path": deploy_config.deploy_path,
"steps": deployment_steps,
"status": "success",
"deployed_at": datetime.utcnow().isoformat(),
"deployed_at": utc_now().isoformat(),
"message": "Deployment completed successfully"
}

View File

@@ -12,6 +12,8 @@ import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/discord", tags=["discord"])
@@ -304,5 +306,5 @@ async def discord_health_check():
"service": "discord",
"status": "operational" if DISCORD_BOT_TOKEN else "not_configured",
"webhook_status": "operational" if DISCORD_WEBHOOK_URL else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -10,6 +10,7 @@ from app.database import get_db
from app.models.user import User
from app.models.email import Email, EmailFolder, EmailFolderType
from app.auth import get_current_active_user
from app.utils import utc_now
router = APIRouter(prefix="/api/email", tags=["Email"])
@@ -154,7 +155,7 @@ async def send_email(
bcc=",".join(email_data.bcc) if email_data.bcc else None,
is_read=False,
is_draft=False,
sent_at=datetime.utcnow()
sent_at=utc_now()
)
db.add(email)
@@ -193,7 +194,7 @@ async def get_email(
# Mark as read if recipient is viewing
if email.recipient_id == current_user.id and not email.is_read:
email.is_read = True
email.read_at = datetime.utcnow()
email.read_at = utc_now()
await db.commit()
return email

View File

@@ -11,6 +11,7 @@ from app.database import get_db
from app.models.user import User
from app.models.file import File, Folder
from app.auth import get_current_active_user
from app.utils import utc_now
router = APIRouter(prefix="/api/files", tags=["Files"])
@@ -217,7 +218,7 @@ async def get_file(
)
# Update last accessed
file.last_accessed = datetime.utcnow()
file.last_accessed = utc_now()
await db.commit()
return file

View File

@@ -19,6 +19,7 @@ import random
from ..database import get_db
from ..auth import get_current_user
from ..models import User
from ..utils import utc_now
router = APIRouter(prefix="/api/games", tags=["games"])
@@ -62,7 +63,7 @@ async def list_cities(
"money": 45000,
"level": 5,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": datetime.utcnow().isoformat()
"updated_at": utc_now().isoformat()
}
]
}

View File

@@ -186,7 +186,7 @@ async def list_commits(
async def list_pull_requests(
owner: str,
repo: str,
state: str = Query("open", regex="^(open|closed|all)$"),
state: str = Query("open", pattern="^(open|closed|all)$"),
page: int = Query(1, ge=1),
per_page: int = Query(30, ge=1, le=100),
current_user: User = Depends(get_current_user)
@@ -220,7 +220,7 @@ async def list_pull_requests(
async def list_issues(
owner: str,
repo: str,
state: str = Query("open", regex="^(open|closed|all)$"),
state: str = Query("open", pattern="^(open|closed|all)$"),
page: int = Query(1, ge=1),
per_page: int = Query(30, ge=1, le=100),
current_user: User = Depends(get_current_user)

View File

@@ -37,7 +37,7 @@ class InferenceRequest(BaseModel):
async def list_models(
search: Optional[str] = Query(None),
filter_task: Optional[str] = Query(None, alias="task"),
sort: str = Query("downloads", regex="^(downloads|likes|trending)$"),
sort: str = Query("downloads", pattern="^(downloads|likes|trending)$"),
limit: int = Query(20, ge=1, le=100),
current_user: User = Depends(get_current_user)
):
@@ -146,7 +146,7 @@ async def run_inference(
@router.get("/datasets")
async def list_datasets(
search: Optional[str] = Query(None),
sort: str = Query("downloads", regex="^(downloads|likes|trending)$"),
sort: str = Query("downloads", pattern="^(downloads|likes|trending)$"),
limit: int = Query(20, ge=1, le=100),
current_user: User = Depends(get_current_user)
):
@@ -194,7 +194,7 @@ async def get_dataset_info(
@router.get("/spaces")
async def list_spaces(
search: Optional[str] = Query(None),
sort: str = Query("likes", regex="^(likes|trending)$"),
sort: str = Query("likes", pattern="^(likes|trending)$"),
limit: int = Query(20, ge=1, le=100),
current_user: User = Depends(get_current_user)
):

View File

@@ -13,6 +13,7 @@ from app.database import get_db
from app.models.blockchain import Block, Wallet
from app.models.user import User
from app.routers.auth import get_current_user
from app.utils import utc_now
router = APIRouter(prefix="/api/miner", tags=["miner"])
@@ -97,7 +98,7 @@ async def get_miner_status(
"""Get current miner status and performance metrics."""
uptime_seconds = 0
if miner_state.started_at:
uptime_seconds = int((datetime.utcnow() - miner_state.started_at).total_seconds())
uptime_seconds = int((utc_now() - miner_state.started_at).total_seconds())
# Simulate some variance in hashrate
current_hashrate = miner_state.hashrate_mhs
@@ -242,7 +243,7 @@ async def control_miner(
raise HTTPException(status_code=400, detail="Miner is already running")
miner_state.is_mining = True
miner_state.started_at = datetime.utcnow()
miner_state.started_at = utc_now()
miner_state.hashrate_mhs = random.uniform(38.0, 45.0) # Simulate hashrate
if control.pool_url:
@@ -268,7 +269,7 @@ async def control_miner(
miner_state.is_mining = False
await asyncio.sleep(1)
miner_state.is_mining = True
miner_state.started_at = datetime.utcnow()
miner_state.started_at = utc_now()
miner_state.hashrate_mhs = random.uniform(38.0, 45.0)
background_tasks.add_task(simulate_mining)
@@ -314,5 +315,5 @@ async def get_pool_info(
"pool_fee": "1%",
"min_payout": 10.0,
"payment_interval_hours": 24,
"last_block_found": (datetime.utcnow() - timedelta(minutes=random.randint(5, 120))).isoformat(),
"last_block_found": (utc_now() - timedelta(minutes=random.randint(5, 120))).isoformat(),
}

View File

@@ -13,6 +13,8 @@ import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/railway", tags=["railway"])
@@ -389,5 +391,5 @@ async def railway_health_check():
return {
"service": "railway",
"status": "operational" if RAILWAY_TOKEN else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -13,6 +13,8 @@ import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/sentry", tags=["sentry"])
@@ -376,5 +378,5 @@ async def sentry_health_check():
return {
"service": "sentry",
"status": "operational" if SENTRY_AUTH_TOKEN else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -7,11 +7,12 @@ Provides endpoints for sending messages, managing channels, and interacting with
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
from datetime import datetime
import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/slack", tags=["slack"])
@@ -277,5 +278,5 @@ async def slack_health_check():
"service": "slack",
"status": "operational" if SLACK_BOT_TOKEN else "not_configured",
"webhook_status": "operational" if SLACK_WEBHOOK_URL else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -8,11 +8,12 @@ Stripe is a payment processing platform for online businesses.
from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, EmailStr
from typing import List, Optional, Dict, Any
from datetime import datetime
import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/stripe", tags=["stripe"])
@@ -324,5 +325,5 @@ async def stripe_health_check():
return {
"service": "stripe",
"status": "operational" if STRIPE_SECRET_KEY else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -14,6 +14,8 @@ import base64
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/twilio", tags=["twilio"])
@@ -255,5 +257,5 @@ async def twilio_health_check():
return {
"service": "twilio",
"status": "operational" if (TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN) else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -13,6 +13,8 @@ import httpx
import os
import logging
from app.utils import utc_now
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/vercel", tags=["vercel"])
@@ -420,5 +422,5 @@ async def vercel_health_check():
return {
"service": "vercel",
"status": "operational" if VERCEL_TOKEN else "not_configured",
"timestamp": datetime.utcnow().isoformat()
"timestamp": utc_now().isoformat()
}

View File

@@ -10,6 +10,7 @@ from app.database import get_db
from app.models.user import User
from app.models.video import Video, VideoView, VideoLike
from app.auth import get_current_active_user
from app.utils import utc_now
router = APIRouter(prefix="/api/videos", tags=["Videos"])
@@ -117,7 +118,7 @@ async def upload_video(
category=video_data.category,
tags=video_data.tags,
is_public=True,
published_at=datetime.utcnow()
published_at=utc_now()
)
db.add(video)

View File

@@ -12,11 +12,11 @@ from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import List, Optional
from datetime import datetime
from ..database import get_db
from ..auth import get_current_user
from ..models import User, File, Folder
from ..utils import utc_now
from pydantic import BaseModel
router = APIRouter(prefix="/api/vscode", tags=["vscode"])
@@ -120,7 +120,7 @@ async def update_file_content(
raise HTTPException(status_code=404, detail="File not found")
# In a real implementation, save to S3 or file system
file.updated_at = datetime.utcnow()
file.updated_at = utc_now()
file.size = len(content.encode('utf-8'))
await db.commit()