File: datetime_unit_test.py

package info (click to toggle)
python-sigima 1.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 25,608 kB
  • sloc: python: 35,251; makefile: 3
file content (176 lines) | stat: -rw-r--r-- 5,516 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file.

"""
DateTime support unit tests
===========================

Unit tests for datetime functionality in SignalObj.
"""

# pylint: disable=invalid-name  # Allows short reference names like x, y, ...

from __future__ import annotations

from datetime import datetime, timedelta

import numpy as np
import pytest

from sigima.objects import create_signal
from sigima.objects.signal.constants import VALID_TIME_UNITS
from sigima.tests.env import execenv


def test_signal_datetime_methods() -> None:
    """Test SignalObj datetime methods."""
    execenv.print("Testing SignalObj datetime methods...")

    # Create datetime data
    base_time = datetime(2025, 10, 6, 10, 0, 0)
    timestamps = [base_time + timedelta(seconds=i) for i in range(10)]
    values = np.sin(np.arange(10) * 0.5)

    format_str = "%Y-%m-%d %H:%M:%S"

    # Test different units
    for unit in VALID_TIME_UNITS:
        # Create signal with initial data
        signal = create_signal(
            "Test Signal", x=np.arange(10, dtype=float), y=values.copy()
        )

        # Initially should not be datetime
        assert not signal.is_x_datetime()

        # Set x from datetime
        signal.set_x_from_datetime(timestamps, unit=unit, format_str=format_str)

        # Check datetime flag
        assert signal.is_x_datetime()
        assert signal.metadata["x_datetime"] is True
        assert signal.xunit == unit
        assert signal.metadata["x_datetime_format"] == format_str

        # Check x data is float
        assert isinstance(signal.x, np.ndarray)
        assert signal.x.dtype in (np.float32, np.float64)

        # Get x as datetime
        dt_values = signal.get_x_as_datetime()
        assert isinstance(dt_values, np.ndarray)
        assert dt_values.dtype == np.dtype("datetime64[ns]")

        # Verify y values are unchanged
        assert np.allclose(signal.y, values)

    execenv.print("  ✓ SignalObj datetime methods test passed")


def test_datetime_with_string_input() -> None:
    """Test datetime conversion from string input."""
    execenv.print("Testing datetime conversion from strings...")

    signal = create_signal("String DateTime Test")

    # Create datetime strings
    date_strings = [
        "2025-10-06 10:00:00",
        "2025-10-06 10:00:01",
        "2025-10-06 10:00:02",
    ]
    values = [1.0, 2.0, 3.0]

    # Set from strings
    signal.set_x_from_datetime(date_strings, unit="s")
    signal.y = values

    # Verify it worked
    assert signal.is_x_datetime()
    assert len(signal.x) == len(date_strings)

    # Get back as datetime
    dt_values = signal.get_x_as_datetime()
    assert len(dt_values) == len(date_strings)

    execenv.print("  ✓ String datetime conversion test passed")


def test_datetime_copy() -> None:
    """Test that datetime metadata is preserved when copying signal."""
    execenv.print("Testing datetime metadata preservation in copy...")

    signal = create_signal("Original")
    timestamps = [datetime(2025, 10, 6, 10, 0, i) for i in range(5)]
    signal.set_x_from_datetime(timestamps, unit="ms")
    signal.y = np.arange(5, dtype=float)

    # Copy signal
    signal_copy = signal.copy()

    # Verify datetime metadata is preserved
    assert signal_copy.is_x_datetime()
    assert signal_copy.xunit == "ms"
    assert np.array_equal(signal.x, signal_copy.x)

    execenv.print("  ✓ Datetime metadata preservation test passed")


def test_datetime_non_datetime_signal() -> None:
    """Test that non-datetime signals work correctly."""
    execenv.print("Testing non-datetime signal behavior...")

    signal = create_signal("Regular Signal", x=np.arange(10), y=np.sin(np.arange(10)))

    # Should not be datetime
    assert not signal.is_x_datetime()

    # get_x_as_datetime should return regular x
    x_data = signal.get_x_as_datetime()
    assert np.array_equal(x_data, signal.x)

    execenv.print("  ✓ Non-datetime signal test passed")


def test_datetime_invalid_unit() -> None:
    """Test that invalid units raise appropriate errors."""
    execenv.print("Testing invalid unit handling...")

    timestamps = [datetime(2025, 10, 6, 10, 0, 0)]

    # Test SignalObj.set_x_from_datetime with invalid unit
    signal = create_signal("Test")
    with pytest.raises(ValueError, match="Invalid unit"):
        signal.set_x_from_datetime(timestamps, unit="invalid")

    execenv.print("  ✓ Invalid unit handling test passed")


def test_datetime_arithmetic_operations() -> None:
    """Test that datetime signals work with arithmetic operations."""
    execenv.print("Testing datetime signal arithmetic...")

    # Create two signals with datetime x
    base_time = datetime(2025, 10, 6, 10, 0, 0)
    timestamps = [base_time + timedelta(seconds=i) for i in range(10)]

    signal1 = create_signal("Signal 1")
    signal1.set_x_from_datetime(timestamps, unit="s")
    signal1.y = np.arange(10, dtype=float)

    signal2 = create_signal("Signal 2")
    signal2.set_x_from_datetime(timestamps, unit="s")
    signal2.y = np.arange(10, dtype=float) * 2

    # The x data should be identical floats
    assert np.array_equal(signal1.x, signal2.x)

    # Verify we can do arithmetic on y
    result_y = signal1.y + signal2.y
    expected_y = np.arange(10, dtype=float) * 3
    assert np.allclose(result_y, expected_y)

    execenv.print("  ✓ Datetime signal arithmetic test passed")


if __name__ == "__main__":
    pytest.main([__file__, "-v"])