From 62d5a5870beee34d8e7a0ba442f6f5c867082aa5 Mon Sep 17 00:00:00 2001 From: tonykcao <98124995+tonykcao@users.noreply.github.com> Date: Fri, 4 Oct 2024 20:49:34 -0400 Subject: [PATCH] feat: added anytime to date module ##936 (#947) * feat: added anytime to date module * broken tests addressed * broken tests addressed * removed out of scope changes * removed out of scope changes --------- Co-authored-by: Tony Cao --- include/faker-cxx/date.h | 13 +++++++++++++ src/modules/date.cpp | 34 ++++++++++++++++++++++++++++++++++ tests/modules/date_test.cpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/include/faker-cxx/date.h b/include/faker-cxx/date.h index f8eec56bc..8d9a3be7a 100644 --- a/include/faker-cxx/date.h +++ b/include/faker-cxx/date.h @@ -13,6 +13,19 @@ enum class DateFormat Timestamp, }; +/** + * @brief Generates a random date between UNIX epoch and 200 years from now + * + * @returns ISO formatted string. + * + * @code + * faker::date::anytime() // "2023-12-08T19:31:32Z" + * faker::date::anytime(DateFormat::ISO) // "2020-06-16T15:24:09Z" + * faker::date::anytime(DateFormat::Timestamp) // "1592321049" + * @endcode + */ +FAKER_CXX_EXPORT std::string anytime(DateFormat dateFormat = DateFormat::ISO); + /** * @brief Generates a random date in the past. * diff --git a/src/modules/date.cpp b/src/modules/date.cpp index d2ddcba98..569454899 100644 --- a/src/modules/date.cpp +++ b/src/modules/date.cpp @@ -46,6 +46,40 @@ std::string betweenDate(const auto& from, const auto& to, DateFormat dateFormat) const auto numberOfHoursInDay = 24; const auto numberOfDaysInYear = 365; +std::string anytime(DateFormat dateFormat) +{ + constexpr int64_t total_seconds = 3600LL * 24LL* 365LL * 200LL; // sec/hr * hr/d * d/yr * years + + int64_t now_seconds = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t max_seconds = now_seconds + total_seconds; + + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dis(0, max_seconds); + + int64_t random_seconds = dis(gen); + + auto timePoint = std::chrono::system_clock::time_point{std::chrono::seconds{random_seconds}}; + std::string result; + + if (dateFormat == DateFormat::Timestamp) + { + result = std::to_string(random_seconds); + } + else + { + time_t timePointTimeT = std::chrono::system_clock::to_time_t(timePoint); + + std::tm utcTime = *std::gmtime(&timePointTimeT); + + std::stringstream ss; + ss << std::put_time(&utcTime, "%Y-%m-%dT%H:%M:%SZ"); + result = ss.str(); + } + + return result; +} + std::string futureDate(int years, DateFormat dateFormat) { const auto startDate = std::chrono::system_clock::now() + std::chrono::hours{1}; diff --git a/tests/modules/date_test.cpp b/tests/modules/date_test.cpp index 7ae2b4e26..a7b36c241 100644 --- a/tests/modules/date_test.cpp +++ b/tests/modules/date_test.cpp @@ -126,6 +126,42 @@ TEST_F(DateTest, shouldGenerateFutureDateTimestamp) EXPECT_TRUE(std::chrono::duration_cast(futureDate - currentDate).count() < secondsInYear); EXPECT_TRUE(futureDate > currentDate); } +TEST_F(DateTest, shouldGenerateAnytimeISO) +{ + const auto currentDate = std::chrono::system_clock::now(); + const auto unixEpoch = std::chrono::system_clock::time_point{}; + + for (int i = 0; i < 100; ++i) + { + const auto anytimeISO = anytime(DateFormat::ISO); + const auto generatedDate = parseISOFormattedStringToTimePoint(anytimeISO); + EXPECT_GT(generatedDate, unixEpoch); + + auto duration = generatedDate - currentDate; + double durationInYears = static_cast(std::chrono::duration_cast(duration).count()) / (365.25 * 24 * 3600); + durationInYears = std::abs(durationInYears); + EXPECT_LT(durationInYears, 201); + } +} + +TEST_F(DateTest, shouldGenerateAnytimeTimestamp) +{ + const auto currentDate = std::chrono::system_clock::now(); + const auto unixEpoch = std::chrono::system_clock::time_point{}; + + for (int i = 0; i < 100; ++i) + { + const auto anytimeTimestamp = anytime(DateFormat::Timestamp); + int64_t timestampSeconds = std::stoll(anytimeTimestamp); + auto generatedDate = std::chrono::system_clock::time_point{std::chrono::seconds{timestampSeconds}}; + EXPECT_GT(generatedDate, unixEpoch); + + auto duration = generatedDate - currentDate; + double durationInYears = static_cast(std::chrono::duration_cast(duration).count()) / (365.25 * 24 * 3600); + durationInYears = std::abs(durationInYears); + EXPECT_LT(durationInYears, 201); + } +} TEST_F(DateTest, shouldGenerateSoonDateISO) {