|
| 1 | +#include <cstdio> |
1 | 2 | #include <numeric> |
2 | 3 | #include <unordered_map> |
3 | 4 | #include <unordered_set> |
@@ -504,6 +505,52 @@ TEST_CASE("testAttributeAndDatasetFields", "[nwb]") |
504 | 505 | std::string readSessionStartTime = sessionStartTimeData->values().data[0]; |
505 | 506 | REQUIRE(readSessionStartTime == sessionStartTime); |
506 | 507 |
|
| 508 | + // Mirrors nwbinspector's check_session_start_time_future_date: the |
| 509 | + // session_start_time written to the file must not be in the future. |
| 510 | + // The old mktime-based UTC offset was wrong during DST, which caused |
| 511 | + // the recorded time to be ~1 hour ahead of actual UTC. |
| 512 | + { |
| 513 | + std::tm parsed {}; |
| 514 | + int offset_h = 0, offset_m = 0; |
| 515 | + char offset_sign = '+'; |
| 516 | + // Parse "YYYY-MM-DDTHH:MM:SS.uuuuuu+HH:MM" |
| 517 | +#if defined(_MSC_VER) |
| 518 | +# pragma warning(push) |
| 519 | +# pragma warning(disable : 4996) // sscanf deprecation |
| 520 | +#endif |
| 521 | + int parsed_fields = std::sscanf(readSessionStartTime.c_str(), |
| 522 | + "%4d-%2d-%2dT%2d:%2d:%2d.%*d%c%2d:%2d", |
| 523 | + &parsed.tm_year, |
| 524 | + &parsed.tm_mon, |
| 525 | + &parsed.tm_mday, |
| 526 | + &parsed.tm_hour, |
| 527 | + &parsed.tm_min, |
| 528 | + &parsed.tm_sec, |
| 529 | + &offset_sign, |
| 530 | + &offset_h, |
| 531 | + &offset_m); |
| 532 | +#if defined(_MSC_VER) |
| 533 | +# pragma warning(pop) |
| 534 | +#endif |
| 535 | + REQUIRE(parsed_fields == 9); |
| 536 | + parsed.tm_year -= 1900; |
| 537 | + parsed.tm_mon -= 1; |
| 538 | + parsed.tm_isdst = 0; |
| 539 | + // Convert struct tm (interpreted as UTC) to time_t |
| 540 | +#if defined(_WIN32) |
| 541 | + std::time_t utc_epoch = _mkgmtime(&parsed); |
| 542 | +#else |
| 543 | + std::time_t utc_epoch = timegm(&parsed); |
| 544 | +#endif |
| 545 | + long offset_total = |
| 546 | + ((long)offset_h * 3600 + offset_m * 60) * (offset_sign == '-' ? -1 : 1); |
| 547 | + // Convert local time to UTC by subtracting the offset |
| 548 | + utc_epoch -= offset_total; |
| 549 | + auto written_tp = std::chrono::system_clock::from_time_t(utc_epoch); |
| 550 | + auto now_tp = std::chrono::system_clock::now(); |
| 551 | + REQUIRE(written_tp <= now_tp); |
| 552 | + } |
| 553 | + |
507 | 554 | auto timestampsReferenceTimeData = nwbfile->readTimestampsReferenceTime(); |
508 | 555 | REQUIRE(timestampsReferenceTimeData->exists()); |
509 | 556 | REQUIRE(timestampsReferenceTimeData->getStorageObjectType() |
|
0 commit comments