Skip to content

Remove cmake chrono flag for date dependency#95

Merged
atimin merged 6 commits intomainfrom
remove-date
Oct 11, 2025
Merged

Remove cmake chrono flag for date dependency#95
atimin merged 6 commits intomainfrom
remove-date

Conversation

@atimin
Copy link
Copy Markdown
Member

@atimin atimin commented Oct 11, 2025

Closes #

Please check if the PR fulfills these requirements

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • CHANGELOG.md has been updated (for bug fixes / features / docs)

What kind of change does this PR introduce?

Refactoring

What was changed?

  • Remove the date package from dependencies and the REDUCT_CPP_USE_STD_CHRONO flag to enable the std;;chrono functions to parse a date.
  • Add a custom function for date parsing

Related issues

#67

Does this PR introduce a breaking change?

No

Other information:

@atimin atimin changed the title Remove use chrono flag date dependency Remove cmake chrono flag date dependency Oct 11, 2025
@atimin atimin changed the title Remove cmake chrono flag date dependency Remove cmake chrono flag for date dependency Oct 11, 2025
@atimin atimin requested a review from Copilot October 11, 2025 19:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Removes the optional date library dependency and associated REDUCT_CPP_USE_STD_CHRONO build flag, replacing prior parsing with a custom ISO8601 UTC parser. Introduces a new internal time parsing helper and updates build/test/configuration to drop the date option.

  • Remove REDUCT_CPP_USE_STD_CHRONO flag and date dependency
  • Add custom parse_iso8601_utc function and refactor parsing call sites
  • Update tests, build scripts, docs, and changelog accordingly

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/reduct/server_api_test.cc Adjusts expected timestamp value after new parsing (precision change).
src/reduct/internal/time_parse.h Adds new custom ISO8601 parsing helper.
src/reduct/internal/serialisation.cc Replaces conditional chrono/date parsing with new helper.
src/reduct/client.cc Replaces conditional chrono/date parsing with new helper.
src/CMakeLists.txt Removes compile definitions for old chrono flag.
conanfile.py Removes option/logic for with_chrono and date requirement.
cmake/InstallDependencies.cmake Removes date dependency handling.
README.md Removes date dependency and flag usage examples.
CMakeLists.txt Removes REDUCT_CPP_USE_STD_CHRONO cache option logic.
CHANGELOG.md Documents removal of flag/library (contains typo).
.github/workflows/ci.yml Cleans CI config of obsolete flag usage.
.github/actions/build-package-vcpkg/action.yml Removes obsolete flag from build invocation.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.


namespace reduct {

// Parse ISO8601 like "2024-10-11T13:45:30Z" or "2024-10-11T13:45:30"
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment claims the function parses strings without a trailing 'Z' (e.g. '...13:45:30'), but the implementation strictly requires and validates a trailing 'Z'/'z'. Update the comment to accurately describe accepted formats.

Suggested change
// Parse ISO8601 like "2024-10-11T13:45:30Z" or "2024-10-11T13:45:30"
// Parse ISO8601 strings ending with 'Z' or 'z', e.g. "2024-10-11T13:45:30Z"

Copilot uses AI. Check for mistakes.
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header uses std::chrono::system_clock but does not include ; relying on transitive includes can lead to build failures. Add #include here.

Suggested change
#include <string>
#include <string>
#include <chrono>

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +25
// Remove trailing 'Z' and fractional part (if present)
std::string clean = iso_str.substr(0, iso_str.size() - 1);
std::size_t dot_pos = clean.find('.');
if (dot_pos != std::string::npos) {
clean = clean.substr(0, dot_pos); // strip everything after '.'
}
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fractional seconds are silently discarded, reducing timestamp precision compared to prior parsing (date::parse can preserve sub-second precision). Consider parsing the fractional component and adding it to the returned time_point instead of truncating.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +39
std::tm tm = {};
std::istringstream ss(clean);

ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");

#if defined(_WIN32)
std::time_t time = _mkgmtime(&tm); // Windows
#else
std::time_t time = timegm(&tm); // POSIX
#endif

if (time == static_cast<std::time_t>(-1)) {
throw std::runtime_error("Invalid time value: " + iso_str);
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stream parse errors are not checked (ss.fail()) before using tm, and treating time == -1 as an error misclassifies the valid timestamp 1969-12-31T23:59:59Z. Check ss.fail() explicitly and only treat parse failure as invalid; avoid using -1 as the sole error sentinel.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +49
#ifndef REDUCTCPP_TIME_PARSE_H

#include <ctime>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>

namespace reduct {

// Parse ISO8601 like "2024-10-11T13:45:30Z" or "2024-10-11T13:45:30"
inline std::chrono::system_clock::time_point parse_iso8601_utc(const std::string& iso_str) {
// Must end with 'Z' or 'z'
if (iso_str.empty() || (iso_str.back() != 'Z' && iso_str.back() != 'z')) {
throw std::runtime_error("Invalid timestamp (missing 'Z'): " + iso_str);
}

// Remove trailing 'Z' and fractional part (if present)
std::string clean = iso_str.substr(0, iso_str.size() - 1);
std::size_t dot_pos = clean.find('.');
if (dot_pos != std::string::npos) {
clean = clean.substr(0, dot_pos); // strip everything after '.'
}

std::tm tm = {};
std::istringstream ss(clean);

ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");

#if defined(_WIN32)
std::time_t time = _mkgmtime(&tm); // Windows
#else
std::time_t time = timegm(&tm); // POSIX
#endif

if (time == static_cast<std::time_t>(-1)) {
throw std::runtime_error("Invalid time value: " + iso_str);
}

return std::chrono::system_clock::from_time_t(time);
}

} // namespace reduct

#define REDUCTCPP_TIME_PARSE_H

#endif // REDUCTCPP_TIME_PARSE_H
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Include guard macro is defined at the end (after code) instead of immediately after #ifndef, which is unconventional and can confuse maintainers. Move #define REDUCTCPP_TIME_PARSE_H to right after the #ifndef and remove the trailing #define.

Copilot uses AI. Check for mistakes.
REQUIRE(info.license->licensee == "ReductSoftware");
REQUIRE(info.license->invoice == "---");
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143696974000);
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143000000000);
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The test asserts a raw tick count which is brittle and obscures intent; consider asserting equality against a constructed time_point (e.g., using time_point_cast to seconds) or comparing parsed string to avoid dependence on representation details.

Suggested change
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143000000000);
// Compare expiry_date to expected value using time_point_cast to seconds for clarity
auto expected_expiry = std::chrono::system_clock::time_point{std::chrono::nanoseconds{1778852143000000000}};
REQUIRE(std::chrono::time_point_cast<std::chrono::seconds>(info.license->expiry_date) ==
std::chrono::time_point_cast<std::chrono::seconds>(expected_expiry));

Copilot uses AI. Check for mistakes.
REQUIRE(info.license->licensee == "ReductSoftware");
REQUIRE(info.license->invoice == "---");
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143696974000);
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143000000000);
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated expected value indicates sub-second precision was lost (previous value differed by <1s). If preserving fractional seconds matters for license expiry semantics, enhance parse_iso8601_utc to retain them rather than truncating.

Suggested change
REQUIRE(info.license->expiry_date.time_since_epoch().count() == 1778852143000000000);
REQUIRE(info.license->expiry_date.time_since_epoch() == std::chrono::nanoseconds(1778852143000000000));

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <[email protected]>
@atimin atimin merged commit ea79ff4 into main Oct 11, 2025
2 checks passed
@atimin atimin deleted the remove-date branch October 11, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants