Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mmif/serialize/mmif.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import math
import warnings
from collections import defaultdict
from datetime import datetime
from datetime import datetime, timezone
from typing import Any, List, Union, Optional, Dict, cast, Iterator

import jsonschema.validators
Expand Down Expand Up @@ -433,7 +433,7 @@ def new_view(self) -> View:
"""
new_view = View()
new_view.id = self.new_view_id()
new_view.metadata.timestamp = datetime.now()
new_view.metadata.timestamp = datetime.now(timezone.utc)
self.add_view(new_view)
return new_view

Expand Down
5 changes: 4 additions & 1 deletion mmif/serialize/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,10 @@ def default(self, obj: 'MmifObject'):
if hasattr(obj, '_serialize'):
return obj._serialize()
elif hasattr(obj, 'isoformat'): # for datetime objects
return obj.isoformat()
s = obj.isoformat()
if s.endswith('+00:00'):
s = s[:-6] + 'Z'
return s
elif hasattr(obj, '__str__'):
return str(obj)
else:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,25 @@ def test_get_label(self):
a = v.new_annotation(AnnotationTypes.BoundingBox)
_ = a._get_label()

def test_timestamp_uses_utc_with_z_suffix(self):
"""Test that timestamps are in UTC with 'Z' suffix to avoid ambiguity"""
from datetime import timezone
mmif_obj = Mmif(validate=False)

new_view = mmif_obj.new_view()
new_view.metadata.app = "http://test.app"

# Verify the timestamp is timezone-aware and uses UTC
self.assertIsNotNone(new_view.metadata.timestamp)
self.assertIsNotNone(new_view.metadata.timestamp.tzinfo)
self.assertEqual(new_view.metadata.timestamp.tzinfo, timezone.utc)

# Verify serialization uses 'Z' suffix instead of '+00:00'
serialized = json.loads(mmif_obj.serialize())
ts = serialized['views'][0]['metadata']['timestamp']
self.assertTrue(ts.endswith('Z'))
self.assertNotIn('+00:00', ts)

def test_get_anchor_point(self):
mmif = Mmif(validate=False)
v1 = mmif.new_view()
Expand Down
Loading