exchange-data-manager/tests/test_timestamps.py

161 lines
5.1 KiB
Python

"""Tests for timestamp utilities."""
import pytest
from datetime import datetime, timezone, timedelta
from exchange_data_manager.utils.timestamps import (
to_millis,
from_millis,
to_seconds,
from_seconds,
ensure_tz_aware,
now_millis,
now_seconds,
)
class TestToMillis:
"""Tests for to_millis function."""
def test_from_seconds(self):
"""Test converting seconds to milliseconds."""
assert to_millis(1709337600) == 1709337600000
def test_from_milliseconds(self):
"""Test that milliseconds pass through unchanged."""
assert to_millis(1709337600000) == 1709337600000
def test_from_float_seconds(self):
"""Test converting float seconds."""
assert to_millis(1709337600.5) == 1709337600500
def test_from_datetime_utc(self):
"""Test converting UTC datetime."""
dt = datetime(2024, 3, 2, 0, 0, 0, tzinfo=timezone.utc)
assert to_millis(dt) == 1709337600000
def test_from_naive_datetime(self):
"""Test converting naive datetime (assumes UTC)."""
dt = datetime(2024, 3, 2, 0, 0, 0)
# Naive datetime treated as UTC
assert to_millis(dt) == 1709337600000
def test_threshold_detection(self):
"""Test automatic detection of seconds vs milliseconds."""
# Values with realistic Unix-second magnitude are treated as seconds
assert to_millis(1709337600) == 1709337600000
# Large values (including pre-2001 ms) are treated as milliseconds
assert to_millis(999999999999) == 999999999999
assert to_millis(1000000000000) == 1000000000000
class TestFromMillis:
"""Tests for from_millis function."""
def test_to_datetime(self):
"""Test converting milliseconds to datetime."""
dt = from_millis(1709337600000)
assert dt.year == 2024
assert dt.month == 3
assert dt.day == 2
assert dt.hour == 0
assert dt.minute == 0
assert dt.second == 0
def test_timezone_aware(self):
"""Test that result is timezone-aware."""
dt = from_millis(1709337600000)
assert dt.tzinfo is not None
assert dt.tzinfo == timezone.utc
class TestToSeconds:
"""Tests for to_seconds function."""
def test_from_seconds(self):
"""Test that seconds pass through unchanged."""
assert to_seconds(1709337600) == 1709337600
def test_from_milliseconds(self):
"""Test converting milliseconds to seconds."""
assert to_seconds(1709337600000) == 1709337600
def test_historical_milliseconds_detected(self):
"""Test that historical ms timestamps are not misclassified as seconds."""
assert to_seconds(999999999999) == 999999999
def test_from_datetime(self):
"""Test converting datetime to seconds."""
dt = datetime(2024, 3, 2, 0, 0, 0, tzinfo=timezone.utc)
assert to_seconds(dt) == 1709337600
class TestFromSeconds:
"""Tests for from_seconds function."""
def test_to_datetime(self):
"""Test converting seconds to datetime."""
dt = from_seconds(1709337600)
assert dt.year == 2024
assert dt.month == 3
assert dt.day == 2
def test_timezone_aware(self):
"""Test that result is timezone-aware."""
dt = from_seconds(1709337600)
assert dt.tzinfo == timezone.utc
class TestEnsureTzAware:
"""Tests for ensure_tz_aware function."""
def test_naive_becomes_utc(self):
"""Test that naive datetime becomes UTC."""
dt = datetime(2024, 3, 2, 0, 0, 0)
result = ensure_tz_aware(dt)
assert result.tzinfo == timezone.utc
def test_aware_unchanged(self):
"""Test that aware datetime is unchanged."""
dt = datetime(2024, 3, 2, 0, 0, 0, tzinfo=timezone.utc)
result = ensure_tz_aware(dt)
assert result == dt
def test_different_timezone_normalized_to_utc(self):
"""Test that non-UTC timezone is normalized to UTC."""
tz = timezone(timedelta(hours=5))
dt = datetime(2024, 3, 2, 0, 0, 0, tzinfo=tz)
result = ensure_tz_aware(dt)
assert result.tzinfo == timezone.utc
assert result.year == 2024
assert result.month == 3
assert result.day == 1
assert result.hour == 19
class TestNowFunctions:
"""Tests for now_millis and now_seconds functions."""
def test_now_millis_reasonable(self):
"""Test that now_millis returns a reasonable value."""
ms = now_millis()
# Should be after 2024-01-01 in milliseconds
assert ms > 1704067200000
# Should be a large number (milliseconds)
assert ms >= 1e12
def test_now_seconds_reasonable(self):
"""Test that now_seconds returns a reasonable value."""
s = now_seconds()
# Should be after 2024-01-01 in seconds
assert s > 1704067200
# Should be a smaller number (seconds)
assert s < 1e12
def test_consistency(self):
"""Test that now_millis and now_seconds are consistent."""
ms = now_millis()
s = now_seconds()
# Should be within 1 second of each other
assert abs(ms // 1000 - s) <= 1