open-space-toolkit-astrodynamics 17.2.0__py312-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. open_space_toolkit_astrodynamics-17.2.0.dist-info/METADATA +30 -0
  2. open_space_toolkit_astrodynamics-17.2.0.dist-info/RECORD +151 -0
  3. open_space_toolkit_astrodynamics-17.2.0.dist-info/WHEEL +5 -0
  4. open_space_toolkit_astrodynamics-17.2.0.dist-info/top_level.txt +1 -0
  5. open_space_toolkit_astrodynamics-17.2.0.dist-info/zip-safe +1 -0
  6. ostk/__init__.py +1 -0
  7. ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-312-x86_64-linux-gnu.so +0 -0
  8. ostk/astrodynamics/__init__.py +11 -0
  9. ostk/astrodynamics/__init__.pyi +720 -0
  10. ostk/astrodynamics/access.pyi +577 -0
  11. ostk/astrodynamics/conjunction/__init__.pyi +121 -0
  12. ostk/astrodynamics/conjunction/close_approach.pyi +89 -0
  13. ostk/astrodynamics/conjunction/message/__init__.pyi +3 -0
  14. ostk/astrodynamics/conjunction/message/ccsds.pyi +705 -0
  15. ostk/astrodynamics/converters.py +130 -0
  16. ostk/astrodynamics/converters.pyi +58 -0
  17. ostk/astrodynamics/data/__init__.pyi +3 -0
  18. ostk/astrodynamics/data/provider.pyi +22 -0
  19. ostk/astrodynamics/dataframe.py +597 -0
  20. ostk/astrodynamics/display.py +281 -0
  21. ostk/astrodynamics/dynamics.pyi +311 -0
  22. ostk/astrodynamics/eclipse.pyi +70 -0
  23. ostk/astrodynamics/estimator.pyi +268 -0
  24. ostk/astrodynamics/event_condition.pyi +910 -0
  25. ostk/astrodynamics/flight/__init__.pyi +626 -0
  26. ostk/astrodynamics/flight/profile/__init__.pyi +99 -0
  27. ostk/astrodynamics/flight/profile/model.pyi +179 -0
  28. ostk/astrodynamics/flight/system.pyi +268 -0
  29. ostk/astrodynamics/guidance_law.pyi +416 -0
  30. ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.17 +0 -0
  31. ostk/astrodynamics/pytrajectory/__init__.py +1 -0
  32. ostk/astrodynamics/pytrajectory/__init__.pyi +3 -0
  33. ostk/astrodynamics/pytrajectory/pystate.py +263 -0
  34. ostk/astrodynamics/pytrajectory/pystate.pyi +66 -0
  35. ostk/astrodynamics/solver.pyi +432 -0
  36. ostk/astrodynamics/test/__init__.py +1 -0
  37. ostk/astrodynamics/test/access/__init__.py +1 -0
  38. ostk/astrodynamics/test/access/test_generator.py +319 -0
  39. ostk/astrodynamics/test/access/test_visibility_criterion.py +201 -0
  40. ostk/astrodynamics/test/conftest.py +119 -0
  41. ostk/astrodynamics/test/conjunction/close_approach/__init__.py +0 -0
  42. ostk/astrodynamics/test/conjunction/close_approach/test_generator.py +228 -0
  43. ostk/astrodynamics/test/conjunction/message/ccsds/__init__.py +1 -0
  44. ostk/astrodynamics/test/conjunction/message/ccsds/conftest.py +325 -0
  45. ostk/astrodynamics/test/conjunction/message/ccsds/data/cdm.json +303 -0
  46. ostk/astrodynamics/test/conjunction/message/ccsds/test_cdm.py +416 -0
  47. ostk/astrodynamics/test/conjunction/test_close_approach.py +244 -0
  48. ostk/astrodynamics/test/data/provider/test_off_nadir.py +58 -0
  49. ostk/astrodynamics/test/dynamics/__init__.py +1 -0
  50. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity.csv +565 -0
  51. ostk/astrodynamics/test/dynamics/data/Tabulated_Earth_Gravity_Truth.csv +100 -0
  52. ostk/astrodynamics/test/dynamics/test_atmospheric_drag.py +128 -0
  53. ostk/astrodynamics/test/dynamics/test_central_body_gravity.py +58 -0
  54. ostk/astrodynamics/test/dynamics/test_dynamics.py +50 -0
  55. ostk/astrodynamics/test/dynamics/test_position_derivative.py +51 -0
  56. ostk/astrodynamics/test/dynamics/test_tabulated.py +138 -0
  57. ostk/astrodynamics/test/dynamics/test_third_body_gravity.py +67 -0
  58. ostk/astrodynamics/test/dynamics/test_thruster.py +157 -0
  59. ostk/astrodynamics/test/eclipse/__init__.py +1 -0
  60. ostk/astrodynamics/test/eclipse/test_generator.py +138 -0
  61. ostk/astrodynamics/test/estimator/test_orbit_determination_solver.py +261 -0
  62. ostk/astrodynamics/test/estimator/test_tle_solver.py +216 -0
  63. ostk/astrodynamics/test/event_condition/test_angular_condition.py +113 -0
  64. ostk/astrodynamics/test/event_condition/test_boolean_condition.py +55 -0
  65. ostk/astrodynamics/test/event_condition/test_brouwer_lyddane_mean_long_condition.py +135 -0
  66. ostk/astrodynamics/test/event_condition/test_coe_condition.py +135 -0
  67. ostk/astrodynamics/test/event_condition/test_instant_condition.py +48 -0
  68. ostk/astrodynamics/test/event_condition/test_logical_condition.py +120 -0
  69. ostk/astrodynamics/test/event_condition/test_real_condition.py +50 -0
  70. ostk/astrodynamics/test/flight/__init__.py +1 -0
  71. ostk/astrodynamics/test/flight/profile/model/test_tabulated_profile.py +115 -0
  72. ostk/astrodynamics/test/flight/system/__init__.py +1 -0
  73. ostk/astrodynamics/test/flight/system/test_propulsion_system.py +64 -0
  74. ostk/astrodynamics/test/flight/system/test_satellite_system.py +83 -0
  75. ostk/astrodynamics/test/flight/system/test_satellite_system_builder.py +71 -0
  76. ostk/astrodynamics/test/flight/test_maneuver.py +231 -0
  77. ostk/astrodynamics/test/flight/test_profile.py +293 -0
  78. ostk/astrodynamics/test/flight/test_system.py +45 -0
  79. ostk/astrodynamics/test/guidance_law/test_constant_thrust.py +177 -0
  80. ostk/astrodynamics/test/guidance_law/test_guidance_law.py +60 -0
  81. ostk/astrodynamics/test/guidance_law/test_heterogeneous_guidance_law.py +164 -0
  82. ostk/astrodynamics/test/guidance_law/test_qlaw.py +209 -0
  83. ostk/astrodynamics/test/solvers/__init__.py +1 -0
  84. ostk/astrodynamics/test/solvers/test_finite_difference_solver.py +196 -0
  85. ostk/astrodynamics/test/solvers/test_least_squares_solver.py +334 -0
  86. ostk/astrodynamics/test/solvers/test_temporal_condition_solver.py +161 -0
  87. ostk/astrodynamics/test/test_access.py +128 -0
  88. ostk/astrodynamics/test/test_converters.py +290 -0
  89. ostk/astrodynamics/test/test_dataframe.py +1355 -0
  90. ostk/astrodynamics/test/test_display.py +184 -0
  91. ostk/astrodynamics/test/test_event_condition.py +80 -0
  92. ostk/astrodynamics/test/test_import.py +26 -0
  93. ostk/astrodynamics/test/test_root_solver.py +70 -0
  94. ostk/astrodynamics/test/test_trajectory.py +126 -0
  95. ostk/astrodynamics/test/test_utilities.py +338 -0
  96. ostk/astrodynamics/test/test_viewer.py +318 -0
  97. ostk/astrodynamics/test/trajectory/__init__.py +1 -0
  98. ostk/astrodynamics/test/trajectory/model/test_nadir_trajectory.py +87 -0
  99. ostk/astrodynamics/test/trajectory/model/test_tabulated_trajectory.py +303 -0
  100. ostk/astrodynamics/test/trajectory/model/test_target_scan_trajectory.py +126 -0
  101. ostk/astrodynamics/test/trajectory/orbit/__init__.py +1 -0
  102. ostk/astrodynamics/test/trajectory/orbit/message/__init__.py +1 -0
  103. ostk/astrodynamics/test/trajectory/orbit/message/spacex/__init__.py +1 -0
  104. ostk/astrodynamics/test/trajectory/orbit/message/spacex/conftest.py +18 -0
  105. ostk/astrodynamics/test/trajectory/orbit/message/spacex/data/opm_1.yaml +44 -0
  106. ostk/astrodynamics/test/trajectory/orbit/message/spacex/test_opm.py +108 -0
  107. ostk/astrodynamics/test/trajectory/orbit/models/__init__.py +1 -0
  108. ostk/astrodynamics/test/trajectory/orbit/models/kepler/__init__.py +1 -0
  109. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean.py +65 -0
  110. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_long.py +102 -0
  111. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_brouwer_lyddane_mean_short.py +102 -0
  112. ostk/astrodynamics/test/trajectory/orbit/models/kepler/test_coe.py +305 -0
  113. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/__init__.py +1 -0
  114. ostk/astrodynamics/test/trajectory/orbit/models/sgp4/test_tle.py +337 -0
  115. ostk/astrodynamics/test/trajectory/orbit/models/test_kepler.py +130 -0
  116. ostk/astrodynamics/test/trajectory/orbit/models/test_modified_equinoctial.py +142 -0
  117. ostk/astrodynamics/test/trajectory/orbit/models/test_propagated.py +234 -0
  118. ostk/astrodynamics/test/trajectory/orbit/models/test_sgp4.py +1 -0
  119. ostk/astrodynamics/test/trajectory/orbit/models/test_tabulated.py +380 -0
  120. ostk/astrodynamics/test/trajectory/orbit/test_model.py +1 -0
  121. ostk/astrodynamics/test/trajectory/orbit/test_pass.py +75 -0
  122. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_angular_velocity.py +30 -0
  123. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quaternion.py +18 -0
  124. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py +136 -0
  125. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py +107 -0
  126. ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py +115 -0
  127. ostk/astrodynamics/test/trajectory/state/test_coordinate_broker.py +84 -0
  128. ostk/astrodynamics/test/trajectory/state/test_coordinate_subset.py +58 -0
  129. ostk/astrodynamics/test/trajectory/state/test_numerical_solver.py +316 -0
  130. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_direction.py +81 -0
  131. ostk/astrodynamics/test/trajectory/test_local_orbital_frame_factory.py +119 -0
  132. ostk/astrodynamics/test/trajectory/test_model.py +1 -0
  133. ostk/astrodynamics/test/trajectory/test_orbit.py +212 -0
  134. ostk/astrodynamics/test/trajectory/test_propagator.py +452 -0
  135. ostk/astrodynamics/test/trajectory/test_segment.py +694 -0
  136. ostk/astrodynamics/test/trajectory/test_sequence.py +550 -0
  137. ostk/astrodynamics/test/trajectory/test_state.py +629 -0
  138. ostk/astrodynamics/test/trajectory/test_state_builder.py +172 -0
  139. ostk/astrodynamics/trajectory/__init__.pyi +1982 -0
  140. ostk/astrodynamics/trajectory/model.pyi +259 -0
  141. ostk/astrodynamics/trajectory/orbit/__init__.pyi +349 -0
  142. ostk/astrodynamics/trajectory/orbit/message/__init__.pyi +3 -0
  143. ostk/astrodynamics/trajectory/orbit/message/spacex.pyi +264 -0
  144. ostk/astrodynamics/trajectory/orbit/model/__init__.pyi +648 -0
  145. ostk/astrodynamics/trajectory/orbit/model/brouwerLyddaneMean.pyi +121 -0
  146. ostk/astrodynamics/trajectory/orbit/model/kepler.pyi +709 -0
  147. ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi +330 -0
  148. ostk/astrodynamics/trajectory/state/__init__.pyi +402 -0
  149. ostk/astrodynamics/trajectory/state/coordinate_subset.pyi +208 -0
  150. ostk/astrodynamics/utilities.py +396 -0
  151. ostk/astrodynamics/viewer.py +851 -0
@@ -0,0 +1,128 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ import numpy as np
6
+
7
+ import ostk.mathematics as mathematics
8
+
9
+ import ostk.physics as physics
10
+
11
+ import ostk.astrodynamics as astrodynamics
12
+
13
+ RealInterval = mathematics.object.RealInterval
14
+ Quaternion = mathematics.geometry.d3.transformation.rotation.Quaternion
15
+ Length = physics.unit.Length
16
+ Angle = physics.unit.Angle
17
+ DateTime = physics.time.DateTime
18
+ Scale = physics.time.Scale
19
+ Duration = physics.time.Duration
20
+ Instant = physics.time.Instant
21
+ Interval = physics.time.Interval
22
+ Transform = physics.coordinate.Transform
23
+ Frame = physics.coordinate.Frame
24
+ Axes = physics.coordinate.Axes
25
+ DynamicProvider = physics.coordinate.frame.provider.Dynamic
26
+ Environment = physics.Environment
27
+ Earth = physics.environment.object.celestial.Earth
28
+ Trajectory = astrodynamics.Trajectory
29
+ Profile = astrodynamics.flight.Profile
30
+ Orbit = astrodynamics.trajectory.Orbit
31
+ State = astrodynamics.trajectory.State
32
+ Pass = astrodynamics.trajectory.orbit.Pass
33
+ Kepler = astrodynamics.trajectory.orbit.model.Kepler
34
+ COE = astrodynamics.trajectory.orbit.model.kepler.COE
35
+ SGP4 = astrodynamics.trajectory.orbit.model.sgp4
36
+ Access = astrodynamics.Access
37
+
38
+
39
+ def test_access_constructors():
40
+ acquisition_of_signal = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
41
+ time_at_closest_approach = Instant.date_time(DateTime(2018, 1, 1, 0, 1, 0), Scale.UTC)
42
+ loss_of_signal = Instant.date_time(DateTime(2018, 1, 1, 0, 2, 0), Scale.UTC)
43
+ max_elevation = Angle.degrees(54.3)
44
+
45
+ access: Access = Access(
46
+ Access.Type.Complete,
47
+ acquisition_of_signal,
48
+ time_at_closest_approach,
49
+ loss_of_signal,
50
+ max_elevation,
51
+ )
52
+
53
+ assert access is not None
54
+ assert isinstance(access, Access)
55
+
56
+
57
+ def test_access_undefined():
58
+ access: Access = Access.undefined()
59
+
60
+ assert access is not None
61
+ assert isinstance(access, Access)
62
+ assert access.is_defined() is False
63
+
64
+
65
+ def test_access_getters():
66
+ acquisition_of_signal = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)
67
+ time_at_closest_approach = Instant.date_time(DateTime(2018, 1, 1, 0, 1, 0), Scale.UTC)
68
+ loss_of_signal = Instant.date_time(DateTime(2018, 1, 1, 0, 2, 0), Scale.UTC)
69
+ max_elevation = Angle.degrees(54.3)
70
+
71
+ access: Access = Access(
72
+ Access.Type.Complete,
73
+ acquisition_of_signal,
74
+ time_at_closest_approach,
75
+ loss_of_signal,
76
+ max_elevation,
77
+ )
78
+
79
+ # get_type
80
+ access_type: Access.Type = access.get_type()
81
+
82
+ assert access_type is not None
83
+ assert isinstance(access_type, Access.Type)
84
+ assert access_type == Access.Type.Complete
85
+
86
+ # get_acquisition_of_signal
87
+ acq_signal: Instant = access.get_acquisition_of_signal()
88
+
89
+ assert acq_signal is not None
90
+ assert isinstance(acq_signal, Instant)
91
+ assert acq_signal == acquisition_of_signal
92
+
93
+ # get_time_of_closest_approach
94
+ closest_approach: Instant = access.get_time_of_closest_approach()
95
+
96
+ assert closest_approach is not None
97
+ assert isinstance(closest_approach, Instant)
98
+ assert closest_approach == time_at_closest_approach
99
+
100
+ # get_loss_of_signal
101
+ loss_signal: Instant = access.get_loss_of_signal()
102
+
103
+ assert loss_signal is not None
104
+ assert isinstance(loss_signal, Instant)
105
+ assert loss_signal == loss_of_signal
106
+
107
+ # get_interval
108
+ interval = access.get_interval()
109
+ assert interval is not None
110
+ assert isinstance(interval, Interval)
111
+
112
+ # get_duration
113
+ duration: Duration = access.get_duration()
114
+
115
+ assert duration is not None
116
+ assert isinstance(duration, Duration)
117
+
118
+ # get_max_elevation
119
+ max_el: Angle = access.get_max_elevation()
120
+
121
+ assert max_el is not None
122
+ assert isinstance(max_el, Angle)
123
+
124
+
125
+ def test_access_string_from_type():
126
+ assert Access.string_from_type(Access.Type.Undefined) == "Undefined"
127
+ assert Access.string_from_type(Access.Type.Complete) == "Complete"
128
+ assert Access.string_from_type(Access.Type.Partial) == "Partial"
@@ -0,0 +1,290 @@
1
+ # Apache License 2.0
2
+
3
+ import pytest
4
+
5
+ from datetime import datetime, timedelta, timezone
6
+
7
+ from ostk.physics.time import Instant
8
+ from ostk.physics.time import Interval
9
+ from ostk.physics.time import DateTime
10
+ from ostk.physics.time import Scale
11
+
12
+ from ostk.astrodynamics.converters import coerce_to_datetime
13
+ from ostk.astrodynamics.converters import coerce_to_instant
14
+ from ostk.astrodynamics.converters import coerce_to_iso
15
+ from ostk.astrodynamics.converters import coerce_to_interval
16
+
17
+
18
+ def test_coerce_to_datetime_success_instant():
19
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
20
+ assert coerce_to_datetime(value) == datetime(
21
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
22
+ )
23
+
24
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
25
+ assert coerce_to_datetime(value) == datetime(
26
+ 2020, 1, 2, 3, 3, 28, 123456, tzinfo=timezone.utc
27
+ )
28
+
29
+
30
+ def test_coerce_to_datetime_success_datetime():
31
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
32
+ assert coerce_to_datetime(value) == value
33
+
34
+ value = datetime(
35
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
36
+ )
37
+ assert coerce_to_datetime(value) == value
38
+
39
+
40
+ def test_coerce_to_datetime_success_iso():
41
+ value = "2020-01-02T03:04:05.123456+00:00"
42
+ assert coerce_to_datetime(value) == datetime(
43
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
44
+ )
45
+
46
+ value = "2020-01-02T03:04:05+00:00"
47
+ assert coerce_to_datetime(value) == datetime(2020, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
48
+
49
+ value = "2020-01-02T03:04:05.123456+01:00"
50
+ assert coerce_to_datetime(value) == datetime(
51
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
52
+ )
53
+
54
+ value = "2020-01-02T03:04:05.123456Z"
55
+ assert coerce_to_datetime(value) == datetime(
56
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc
57
+ )
58
+
59
+ value = "2020-01-02T03:04:05Z"
60
+ assert coerce_to_datetime(value) == datetime(2020, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
61
+
62
+
63
+ def test_coerce_to_datetime_failure():
64
+ with pytest.raises(TypeError):
65
+ coerce_to_datetime(False)
66
+
67
+ with pytest.raises(Exception):
68
+ coerce_to_datetime("some_ill_formed_iso")
69
+
70
+
71
+ def test_coerce_to_instant_success_datetime():
72
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
73
+ assert coerce_to_instant(value) == Instant.date_time(
74
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
75
+ )
76
+
77
+ value = datetime(
78
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
79
+ )
80
+ assert coerce_to_instant(value) == Instant.date_time(
81
+ DateTime(2020, 1, 2, 2, 4, 5, 123, 456), Scale.UTC
82
+ )
83
+
84
+
85
+ def test_coerce_to_instant_success_instant():
86
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
87
+ assert coerce_to_instant(value) == value
88
+
89
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
90
+ assert coerce_to_instant(value) == value
91
+
92
+
93
+ def test_coerce_to_instant_success_iso():
94
+ value = "2020-01-02T03:04:05.123456+00:00"
95
+ assert coerce_to_instant(value) == Instant.date_time(
96
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
97
+ )
98
+
99
+ value = "2020-01-02T03:04:05+00:00"
100
+ assert coerce_to_instant(value) == Instant.date_time(
101
+ DateTime(2020, 1, 2, 3, 4, 5), Scale.UTC
102
+ )
103
+
104
+ value = "2020-01-02T03:04:05.123456+01:00"
105
+ assert coerce_to_instant(value) == Instant.date_time(
106
+ DateTime(2020, 1, 2, 2, 4, 5, 123, 456), Scale.UTC
107
+ )
108
+
109
+ value = "2020-01-02T03:04:05.123456Z"
110
+ assert coerce_to_instant(value) == Instant.date_time(
111
+ DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC
112
+ )
113
+
114
+ value = "2020-01-02T03:04:05Z"
115
+ assert coerce_to_instant(value) == Instant.date_time(
116
+ DateTime(
117
+ 2020,
118
+ 1,
119
+ 2,
120
+ 3,
121
+ 4,
122
+ 5,
123
+ ),
124
+ Scale.UTC,
125
+ )
126
+
127
+
128
+ def test_coerce_to_instant_failure():
129
+ with pytest.raises(TypeError):
130
+ coerce_to_instant(False)
131
+
132
+ with pytest.raises(Exception):
133
+ coerce_to_instant("some_ill_formed_iso")
134
+
135
+
136
+ def test_coerce_to_iso_success_datetime():
137
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
138
+ assert (
139
+ coerce_to_iso(value, timespec="microseconds")
140
+ == "2020-01-02T03:04:05.123456+00:00"
141
+ )
142
+
143
+ value = datetime(
144
+ 2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone(timedelta(seconds=3600))
145
+ )
146
+ assert (
147
+ coerce_to_iso(value, timespec="microseconds")
148
+ == "2020-01-02T03:04:05.123456+01:00"
149
+ )
150
+
151
+ value = datetime(2020, 1, 2, 3, 4, 5, 123456, tzinfo=timezone.utc)
152
+ assert (
153
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
154
+ )
155
+
156
+ value = datetime(2020, 1, 2, 3, 4, 5, 0, tzinfo=timezone.utc)
157
+ assert (
158
+ coerce_to_iso(value, timespec="microseconds")
159
+ == "2020-01-02T03:04:05.000000+00:00"
160
+ )
161
+
162
+
163
+ def test_coerce_to_iso_success_instant():
164
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
165
+ assert (
166
+ coerce_to_iso(value, timespec="microseconds")
167
+ == "2020-01-02T03:04:05.123456+00:00"
168
+ )
169
+
170
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.TAI)
171
+ assert (
172
+ coerce_to_iso(value, timespec="microseconds")
173
+ == "2020-01-02T03:03:28.123456+00:00"
174
+ )
175
+
176
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123, 456), Scale.UTC)
177
+ assert (
178
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
179
+ )
180
+
181
+ value = Instant.date_time(DateTime(2020, 1, 2, 3, 4, 5, 123), Scale.UTC)
182
+ assert (
183
+ coerce_to_iso(value, timespec="microseconds")
184
+ == "2020-01-02T03:04:05.123000+00:00"
185
+ )
186
+
187
+
188
+ def test_coerce_to_iso_success_iso():
189
+ value = "2020-01-02T03:04:05.123456+00:00"
190
+ assert coerce_to_iso(value, timespec="microseconds") == value
191
+
192
+ value = "2020-01-02T03:04:05.123456+01:00"
193
+ assert coerce_to_iso(value, timespec="microseconds") == value
194
+
195
+ value = "2020-01-02T03:04:05.123456+00:00"
196
+ assert (
197
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
198
+ )
199
+
200
+ value = "2020-01-02T03:04:05.123+00:00"
201
+ assert (
202
+ coerce_to_iso(value, timespec="microseconds")
203
+ == "2020-01-02T03:04:05.123000+00:00"
204
+ )
205
+
206
+ value = "2020-01-02T03:04:05+00:00"
207
+ assert (
208
+ coerce_to_iso(value, timespec="microseconds")
209
+ == "2020-01-02T03:04:05.000000+00:00"
210
+ )
211
+
212
+ value = "2020-01-02T03:04:05.123456Z"
213
+ assert (
214
+ coerce_to_iso(value, timespec="microseconds")
215
+ == "2020-01-02T03:04:05.123456+00:00"
216
+ )
217
+
218
+ value = "2020-01-02T03:04:05.123456Z"
219
+ assert (
220
+ coerce_to_iso(value, timespec="milliseconds") == "2020-01-02T03:04:05.123+00:00"
221
+ )
222
+
223
+ value = "2020-01-02T03:04:05.123Z"
224
+ assert (
225
+ coerce_to_iso(value, timespec="microseconds")
226
+ == "2020-01-02T03:04:05.123000+00:00"
227
+ )
228
+
229
+ value = "2020-01-02T03:04:05Z"
230
+ assert (
231
+ coerce_to_iso(value, timespec="microseconds")
232
+ == "2020-01-02T03:04:05.000000+00:00"
233
+ )
234
+
235
+
236
+ def test_coerce_to_iso_failure():
237
+ with pytest.raises(TypeError):
238
+ coerce_to_iso(False)
239
+
240
+ with pytest.raises(Exception):
241
+ coerce_to_iso("some_ill_formed_iso")
242
+
243
+
244
+ @pytest.mark.parametrize(
245
+ "value",
246
+ [
247
+ (
248
+ Interval.closed(
249
+ Instant.date_time(DateTime(2020, 1, 1), Scale.UTC),
250
+ Instant.date_time(DateTime(2020, 1, 2), Scale.UTC),
251
+ )
252
+ ),
253
+ (
254
+ (
255
+ Instant.date_time(DateTime(2020, 1, 1), Scale.UTC),
256
+ Instant.date_time(DateTime(2020, 1, 2), Scale.UTC),
257
+ )
258
+ ),
259
+ (
260
+ [
261
+ Instant.date_time(DateTime(2020, 1, 1), Scale.UTC),
262
+ Instant.date_time(DateTime(2020, 1, 2), Scale.UTC),
263
+ ]
264
+ ),
265
+ (
266
+ (
267
+ datetime(2020, 1, 1, tzinfo=timezone.utc),
268
+ datetime(2020, 1, 2, tzinfo=timezone.utc),
269
+ )
270
+ ),
271
+ (
272
+ [
273
+ datetime(2020, 1, 1, tzinfo=timezone.utc),
274
+ datetime(2020, 1, 2, tzinfo=timezone.utc),
275
+ ]
276
+ ),
277
+ (
278
+ [
279
+ "2020-01-01T00:00:00Z",
280
+ "2020-01-02T00:00:00Z",
281
+ ]
282
+ ),
283
+ ("[2020-01-01T00:00:00Z - 2020-01-02T00:00:00Z] [UTC]"),
284
+ ],
285
+ )
286
+ def test_coerce_to_interval(value):
287
+ assert coerce_to_interval(value) == Interval.closed(
288
+ Instant.date_time(DateTime(2020, 1, 1), Scale.UTC),
289
+ Instant.date_time(DateTime(2020, 1, 2), Scale.UTC),
290
+ )