diff --git a/nomad/metainfo/metainfo.py b/nomad/metainfo/metainfo.py index ac712c9800d25127c5af08c67af1a8e3e32b05a7..f0c0383aa6a5c0733ee1dfb0ef93a4e759a05e7b 100644 --- a/nomad/metainfo/metainfo.py +++ b/nomad/metainfo/metainfo.py @@ -815,6 +815,11 @@ class _Datetime(DataType): except ValueError: pass + try: + return datetime.fromisoformat(datetime_str) + except ValueError: + pass + raise TypeError('Invalid date literal %s' % datetime_str) def _convert(self, value): @@ -833,6 +838,11 @@ class _Datetime(DataType): if not isinstance(value, datetime): raise TypeError('%s is not a datetime.' % value) + if value.tzinfo is None: + value = value.replace(tzinfo=pytz.utc) + else: + value = value.astimezone(pytz.utc) + return value def set_normalize(self, section: 'MSection', quantity_def: 'Quantity', value: Any) -> Any: @@ -842,7 +852,6 @@ class _Datetime(DataType): if value is None: return None - value.replace(tzinfo=pytz.utc) return value.isoformat() def deserialize(self, section: 'MSection', quantity_def: 'Quantity', value: Any) -> Any: diff --git a/tests/metainfo/test_quantities.py b/tests/metainfo/test_quantities.py index 4603726e284ad40ec2feb4322a5eaa042d68b466..931536f10a6fb1bd720498997c353287ec295170 100644 --- a/tests/metainfo/test_quantities.py +++ b/tests/metainfo/test_quantities.py @@ -19,7 +19,7 @@ import pytest import json import datetime - +import pytz from nomad.metainfo import MSection, Quantity, Unit, units, JSON, Dimension, Datetime, Capitalized, Bytes @@ -33,7 +33,8 @@ from nomad.metainfo import MSection, Quantity, Unit, units, JSON, Dimension, Dat pytest.param(Dimension, '*', id='Dimension-*'), pytest.param(Dimension, 1, id='Dimension-1'), pytest.param(Dimension, 'quantity', id='Dimension-quantity'), - pytest.param(Datetime, datetime.datetime.now(), id='Datetime'), + pytest.param(Datetime, datetime.datetime.now(datetime.timezone.utc), id='Datetime'), + pytest.param(Datetime, datetime.datetime.now(pytz.timezone('America/Los_Angeles')), id='Datetime'), pytest.param(Capitalized, 'Hello', id='Capitalize'), pytest.param(Bytes, b'hello', id='Bytes') ]) @@ -66,6 +67,7 @@ def test_basic_types(def_type, value): pytest.param(Datetime, 'Wed, 01 Jan 1970 00:00:00 -0100', None, id='Datetime-rfc822'), pytest.param(Datetime, '1970-01-01T00:00:00Z', None, id='Datetime-aniso861-time'), pytest.param(Datetime, '1970-01-01', None, id='Datetime-aniso861-date'), + pytest.param(Datetime, '2022-05-19T05:16:32.237914-07:00', None, id='Datetime-conversion-from-localtime-to-UTC'), pytest.param(Capitalized, 'hello', 'Hello', id='Capitalize') ]) def test_value_normalization(def_type, orig_value, normalized_value): diff --git a/tests/processing/test_edit_metadata.py b/tests/processing/test_edit_metadata.py index 292aaaaef05314c684584dd5c4edf8f13dd05375..afadeaf3526ca46151db30573f73d5daee471a72 100644 --- a/tests/processing/test_edit_metadata.py +++ b/tests/processing/test_edit_metadata.py @@ -159,7 +159,9 @@ def convert_to_comparable_value_single(quantity, value, format, user): elif quantity.type == metainfo.Datetime: if not value: return None - return value[0:22] # Only compare to the millisecond level (mongo's maximal precision) + # datetime that is returned from Datetime class now has the timezone information. + # Hence, need to drop the last 3 elements in the datetime string [:19] instead of [:22] + return value[0:19] # Only compare to the millisecond level (mongo's maximal precision). elif isinstance(quantity.type, metainfo.Reference): # Should be reference verify_reference = quantity.type.target_section_def.section_cls