1+ import datetime
2+
13import numpy as np
24import pytest
35from packaging import version
@@ -181,6 +183,39 @@ def test_get_ds_structure(experiment):
181183 assert structure == expected_structure
182184
183185
186+ def test_split_timestamp_naive ():
187+ # The legacy qcodes timestamp format has no timezone information and is
188+ # returned as-is (split into date and time). Expected values are hard-coded
189+ # so this does not depend on the helper's own logic.
190+ assert _split_timestamp ("2026-07-31 10:27:25" ) == ("2026-07-31" , "10:27:25" )
191+
192+
193+ def test_split_timestamp_none_and_invalid ():
194+ assert _split_timestamp (None ) == ("" , "" )
195+ assert _split_timestamp ("" ) == ("" , "" )
196+ assert _split_timestamp ("not a timestamp" ) == ("" , "" )
197+
198+
199+ def test_split_timestamp_timezone_aware_rendered_in_local_time ():
200+ # The new qcodes timestamp format includes the UTC offset. Such timestamps
201+ # must be converted to the local timezone of the machine before being split.
202+ # We compute the expected local date/time independently from the helper:
203+ # take a fixed absolute instant, convert it to local wall-clock time via
204+ # ``datetime.fromtimestamp`` (a different code path than the helper), and
205+ # verify the helper agrees for the same instant given in different offsets.
206+ utc_instant = datetime .datetime (2026 , 7 , 31 , 8 , 27 , 25 ,
207+ tzinfo = datetime .timezone .utc )
208+ local = datetime .datetime .fromtimestamp (utc_instant .timestamp ())
209+ expected = (local .strftime ("%Y-%m-%d" ), local .strftime ("%H:%M:%S" ))
210+
211+ # Same instant expressed as UTC (+00:00) and as +02:00.
212+ assert _split_timestamp ("2026-07-31 08:27:25+00:00" ) == expected
213+ assert _split_timestamp ("2026-07-31 10:27:25+02:00" ) == expected
214+ # qcodes renders the offset without a colon (e.g. "+0000"); ensure that
215+ # format is handled too.
216+ assert _split_timestamp ("2026-07-31 08:27:25+0000" ) == expected
217+
218+
184219def test_get_ds_info (experiment ):
185220 N = 5
186221
@@ -203,20 +238,19 @@ def test_get_ds_info(experiment):
203238 # timestamps are difficult to test for, so we will cheat here and
204239 # instead of hard-coding timestamps we will just get them from the dataset
205240 # The same applies to the guid as it contains the timestamp.
206- # We parse the qcodes timestamps the same way ``get_ds_info`` does, so that
207- # this test is robust to the qcodes timestamp format (in particular the
208- # newer format that appends the local UTC offset, e.g.
209- # "2026-07-31 10:27:25+0200").
210- started_date , started_time = _split_timestamp (dataset .run_timestamp ())
211- completed_date , completed_time = _split_timestamp (dataset .completed_timestamp ())
241+ # To avoid testing ``get_ds_info`` against the very helper it uses
242+ # (``_split_timestamp``), we derive the expected local date/time
243+ # independently from the raw unix timestamps exposed by qcodes.
244+ started = datetime .datetime .fromtimestamp (dataset .run_timestamp_raw )
245+ completed = datetime .datetime .fromtimestamp (dataset .completed_timestamp_raw )
212246
213247 expected_ds_info = {
214248 'experiment' : '2d_softsweep' ,
215249 'sample' : 'no sample' ,
216- 'completed_date' : completed_date ,
217- 'completed_time' : completed_time ,
218- 'started_date' : started_date ,
219- 'started_time' : started_time ,
250+ 'completed_date' : completed . strftime ( '%Y-%m-%d' ) ,
251+ 'completed_time' : completed . strftime ( '%H:%M:%S' ) ,
252+ 'started_date' : started . strftime ( '%Y-%m-%d' ) ,
253+ 'started_time' : started . strftime ( '%H:%M:%S' ) ,
220254 'name' : 'results' ,
221255 'structure' : None ,
222256 'records' : 0 ,
0 commit comments