mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-19 19:25:53 +00:00
@@ -22,6 +22,7 @@
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/RPCHelpers.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
@@ -65,10 +66,8 @@ TimeFormatValidator::verify(boost::json::value const& value, std::string_view ke
|
||||
if (not value.as_object().at(key).is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||
|
||||
std::tm time = {};
|
||||
std::stringstream stream(value_to<std::string>(value.as_object().at(key)));
|
||||
stream >> std::get_time(&time, format_.c_str());
|
||||
if (stream.fail())
|
||||
auto const ret = util::SystemTpFromUTCStr(value_to<std::string>(value.as_object().at(key)), format_);
|
||||
if (!ret)
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||
|
||||
return {};
|
||||
|
||||
@@ -22,19 +22,16 @@
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/JS.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <boost/json/conversion.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/basics/strHex.h>
|
||||
#include <xrpl/protocol/jss.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <ranges>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -61,18 +58,16 @@ LedgerIndexHandler::process(LedgerIndexHandler::Input input, Context const& ctx)
|
||||
return fillOutputByIndex(maxIndex);
|
||||
|
||||
auto const convertISOTimeStrToTicks = [](std::string const& isoTimeStr) {
|
||||
std::tm time = {};
|
||||
std::stringstream ss(isoTimeStr);
|
||||
ss >> std::get_time(&time, DATE_FORMAT);
|
||||
return std::chrono::system_clock::from_time_t(std::mktime(&time)).time_since_epoch().count();
|
||||
auto const systemTime = util::SystemTpFromUTCStr(isoTimeStr, DATE_FORMAT);
|
||||
// systemTime must be valid after validation passed
|
||||
return systemTime->time_since_epoch().count();
|
||||
};
|
||||
|
||||
auto const ticks = convertISOTimeStrToTicks(*input.date);
|
||||
|
||||
auto const earlierThan = [&](std::uint32_t ledgerIndex) {
|
||||
auto const header = sharedPtrBackend_->fetchLedgerBySequence(ledgerIndex, ctx.yield);
|
||||
auto const ledgerTime =
|
||||
std::chrono::system_clock::time_point{header->closeTime.time_since_epoch() + ripple::epoch_offset};
|
||||
auto const ledgerTime = util::SystemTpFromLedgerCloseTime(header->closeTime);
|
||||
return ticks < ledgerTime.time_since_epoch().count();
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ target_sources(
|
||||
requests/impl/SslContext.cpp
|
||||
Taggable.cpp
|
||||
TerminationHandler.cpp
|
||||
TimeUtils.cpp
|
||||
TxUtils.cpp
|
||||
LedgerUtils.cpp
|
||||
)
|
||||
|
||||
42
src/util/TimeUtils.cpp
Normal file
42
src/util/TimeUtils.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <xrpl/basics/chrono.h>
|
||||
|
||||
namespace util {
|
||||
[[nodiscard]] std::optional<std::chrono::system_clock::time_point>
|
||||
SystemTpFromUTCStr(std::string const& dateStr, std::string const& format)
|
||||
{
|
||||
std::tm timeStruct;
|
||||
auto const ret = strptime(dateStr.c_str(), format.c_str(), &timeStruct);
|
||||
if (ret == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::chrono::system_clock::from_time_t(timegm(&timeStruct));
|
||||
}
|
||||
|
||||
[[nodiscard]] std::chrono::system_clock::time_point
|
||||
SystemTpFromLedgerCloseTime(ripple::NetClock::time_point closeTime)
|
||||
{
|
||||
return std::chrono::system_clock::time_point{closeTime.time_since_epoch() + ripple::epoch_offset};
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
46
src/util/TimeUtils.hpp
Normal file
46
src/util/TimeUtils.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/chrono.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
|
||||
namespace util {
|
||||
|
||||
/**
|
||||
* @brief Convert a UTC date string to a system_clock::time_point if possible.
|
||||
* @param dateStr The UTC date string to convert.
|
||||
* @param format The format of the date string.
|
||||
* @return The system_clock::time_point if the conversion was successful, otherwise std::nullopt.
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::chrono::system_clock::time_point>
|
||||
SystemTpFromUTCStr(std::string const& dateStr, std::string const& format);
|
||||
|
||||
/**
|
||||
* @brief Convert a ledger close time which is XRPL network clock to a system_clock::time_point.
|
||||
* @param closeTime The ledger close time to convert.
|
||||
* @return The system_clock::time_point.
|
||||
*/
|
||||
[[nodiscard]] std::chrono::system_clock::time_point
|
||||
SystemTpFromLedgerCloseTime(ripple::NetClock::time_point closeTime);
|
||||
|
||||
} // namespace util
|
||||
@@ -119,6 +119,7 @@ target_sources(
|
||||
util/RandomTests.cpp
|
||||
util/RetryTests.cpp
|
||||
util/SignalsHandlerTests.cpp
|
||||
util/TimeUtilsTests.cpp
|
||||
util/TxUtilTests.cpp
|
||||
# Webserver
|
||||
web/AdminVerificationTests.cpp
|
||||
|
||||
@@ -90,6 +90,24 @@ TEST_F(RPCLedgerIndexTest, EarlierThanMinLedger)
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(RPCLedgerIndexTest, ChangeTimeZone)
|
||||
{
|
||||
setenv("TZ", "EST+5", 1);
|
||||
backend->setRange(RANGEMIN, RANGEMAX);
|
||||
auto const handler = AnyHandler{LedgerIndexHandler{backend}};
|
||||
auto const req = json::parse(R"({"date": "2024-06-25T12:23:05Z"})");
|
||||
auto const ledgerHeader =
|
||||
CreateLedgerHeaderWithUnixTime(LEDGERHASH, RANGEMIN, 1719318190); //"2024-06-25T12:23:10Z"
|
||||
EXPECT_CALL(*backend, fetchLedgerBySequence(RANGEMIN, _)).WillOnce(Return(ledgerHeader));
|
||||
runSpawn([&](auto yield) {
|
||||
auto const output = handler.process(req, Context{yield});
|
||||
ASSERT_FALSE(output);
|
||||
auto const err = rpc::makeError(output.result.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "lgrNotFound");
|
||||
});
|
||||
unsetenv("TZ");
|
||||
}
|
||||
|
||||
struct LedgerIndexTestsCaseBundle {
|
||||
std::string testName;
|
||||
std::string json;
|
||||
|
||||
51
tests/unit/util/TimeUtilsTests.cpp
Normal file
51
tests/unit/util/TimeUtilsTests.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2024, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/TimeUtils.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(TimeUtilTests, SystemTpFromUTCStrSuccess)
|
||||
{
|
||||
auto const tp = util::SystemTpFromUTCStr("2024-01-01T10:50:40Z", "%Y-%m-%dT%H:%M:%SZ");
|
||||
ASSERT_TRUE(tp.has_value());
|
||||
auto const time = std::chrono::system_clock::to_time_t(tp.value());
|
||||
std::tm timeStruct;
|
||||
gmtime_r(&time, &timeStruct);
|
||||
EXPECT_EQ(timeStruct.tm_year + 1900, 2024);
|
||||
EXPECT_EQ(timeStruct.tm_mon, 0);
|
||||
EXPECT_EQ(timeStruct.tm_mday, 1);
|
||||
EXPECT_EQ(timeStruct.tm_hour, 10);
|
||||
EXPECT_EQ(timeStruct.tm_min, 50);
|
||||
EXPECT_EQ(timeStruct.tm_sec, 40);
|
||||
}
|
||||
|
||||
TEST(TimeUtilTests, SystemTpFromUTCStrFail)
|
||||
{
|
||||
auto const tp = util::SystemTpFromUTCStr("2024-01-01T", "%Y-%m-%dT%H:%M:%SZ");
|
||||
ASSERT_FALSE(tp.has_value());
|
||||
}
|
||||
|
||||
TEST(TimeUtilTests, SystemTpFromLedgerCloseTime)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
||||
auto const tp = util::SystemTpFromLedgerCloseTime(ripple::NetClock::time_point{seconds{0}});
|
||||
EXPECT_EQ(tp.time_since_epoch(), ripple::epoch_offset);
|
||||
}
|
||||
Reference in New Issue
Block a user