fix: P0 Windows Edge path, add time localization, show --output, cleanup tech debt
- Fix auth.py subprocess script Windows Edge cookie path inconsistency - Add timeutil.py for UTC→local time and relative time conversion - Integrate time localization into formatter.py and serialization.py - Add --output/-o option to show command for saving tweet detail as JSON - Remove constants.py legacy aliases (USER_AGENT, SEC_CH_UA) - Remove client.py backward-compat delegation methods and re-exports - Update test imports to use parser module directly
This commit is contained in:
71
twitter_cli/timeutil.py
Normal file
71
twitter_cli/timeutil.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""Time formatting utilities for twitter-cli.
|
||||
|
||||
Converts Twitter API timestamps (e.g. "Sat Mar 08 12:00:00 +0000 2026")
|
||||
into human-friendly local time and relative time strings.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Twitter API timestamp format: "Sat Mar 08 12:00:00 +0000 2026"
|
||||
_TWITTER_TIME_FORMAT = "%a %b %d %H:%M:%S %z %Y"
|
||||
|
||||
|
||||
def _parse_twitter_time(created_at: str) -> Optional[datetime]:
|
||||
"""Parse a Twitter API timestamp into a timezone-aware datetime."""
|
||||
if not created_at:
|
||||
return None
|
||||
try:
|
||||
return datetime.strptime(created_at, _TWITTER_TIME_FORMAT)
|
||||
except (ValueError, TypeError):
|
||||
logger.debug("Failed to parse Twitter timestamp: %s", created_at)
|
||||
return None
|
||||
|
||||
|
||||
def format_local_time(created_at: str) -> str:
|
||||
"""Convert Twitter timestamp to local time string.
|
||||
|
||||
Returns "2026-03-14 21:08" or the original string on parse failure.
|
||||
"""
|
||||
dt = _parse_twitter_time(created_at)
|
||||
if dt is None:
|
||||
return created_at
|
||||
local_dt = dt.astimezone()
|
||||
return local_dt.strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
|
||||
def format_relative_time(created_at: str) -> str:
|
||||
"""Convert Twitter timestamp to a relative time string.
|
||||
|
||||
Returns e.g. "2m ago", "3h ago", "5d ago", or the original string on failure.
|
||||
"""
|
||||
dt = _parse_twitter_time(created_at)
|
||||
if dt is None:
|
||||
return created_at
|
||||
now = datetime.now(timezone.utc)
|
||||
delta = now - dt
|
||||
seconds = int(delta.total_seconds())
|
||||
|
||||
if seconds < 0:
|
||||
return "just now"
|
||||
if seconds < 60:
|
||||
return "%ds ago" % seconds
|
||||
minutes = seconds // 60
|
||||
if minutes < 60:
|
||||
return "%dm ago" % minutes
|
||||
hours = minutes // 60
|
||||
if hours < 24:
|
||||
return "%dh ago" % hours
|
||||
days = hours // 24
|
||||
if days < 30:
|
||||
return "%dd ago" % days
|
||||
months = days // 30
|
||||
if months < 12:
|
||||
return "%dmo ago" % months
|
||||
years = days // 365
|
||||
return "%dy ago" % years
|
||||
Reference in New Issue
Block a user