Skip to content

Commit 5a2cf05

Browse files
Ankit PachouriAnkit Pachouri
authored andcommitted
adjust datetime str nanoseconds to microseconds
1 parent c416190 commit 5a2cf05

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

stix2/test/v21/test_timestamp_precision.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ def test_stix_datetime():
7171

7272
@pytest.mark.parametrize(
7373
"us, precision, precision_constraint, expected_truncated_us", [
74+
(123456789, Precision.ANY, PrecisionConstraint.EXACT, 123456),
75+
(123456789, Precision.SECOND, PrecisionConstraint.EXACT, 0),
76+
(123456789, Precision.SECOND, PrecisionConstraint.MIN, 123456),
77+
(123456789, Precision.MILLISECOND, PrecisionConstraint.EXACT, 123000),
78+
(123456789, Precision.MILLISECOND, PrecisionConstraint.MIN, 123456),
7479
(123456, Precision.ANY, PrecisionConstraint.EXACT, 123456),
7580
(123456, Precision.SECOND, PrecisionConstraint.EXACT, 0),
7681
(123456, Precision.SECOND, PrecisionConstraint.MIN, 123456),

stix2/utils.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,32 @@ def format_datetime(dttm):
212212
return ts
213213

214214

215+
def adjust_nanoseconds(value):
216+
"""
217+
This function checks if the timestamp has exactly 9 digits after the decimal
218+
and ends with 'Z'. If it does, it adjusts to microseconds precision (6 digits).
219+
Otherwise, it returns the value unchanged.
220+
"""
221+
222+
# Return the value if there is no decimal or
223+
# if the frac_seconds_part length is not 10
224+
if '.' not in value:
225+
return value
226+
227+
seconds_part, frac_seconds_part = value.split('.', 1)
228+
229+
if len(frac_seconds_part) != 10:
230+
return value
231+
232+
# Ensure the fractional part has exactly 10 characters (9 digits + 1 'Z')
233+
if frac_seconds_part[:9].isdigit() and frac_seconds_part[9] == 'Z':
234+
# Adjust precision to microseconds (6 digits)
235+
microseconds_part = frac_seconds_part[:6]
236+
value = f'{seconds_part}.{microseconds_part}Z'
237+
238+
return value
239+
240+
215241
def parse_into_datetime(
216242
value, precision=Precision.ANY,
217243
precision_constraint=PrecisionConstraint.EXACT,
@@ -245,6 +271,8 @@ def parse_into_datetime(
245271
else:
246272
# value isn't a date or datetime object so assume it's a string
247273
fmt = _TIMESTAMP_FORMAT_FRAC if "." in value else _TIMESTAMP_FORMAT
274+
# adjust value precision from nanoseconds to microseconds if applicable
275+
value = adjust_nanoseconds(value)
248276
try:
249277
parsed = dt.datetime.strptime(value, fmt)
250278
except (TypeError, ValueError):

0 commit comments

Comments
 (0)