Skip to content

Commit

Permalink
Merge pull request #1 from SOCI/master
Browse files Browse the repository at this point in the history
Get latests updates
  • Loading branch information
cstiborg authored Oct 3, 2023
2 parents a4fb0b0 + 1b14b7c commit c4ff390
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ task:
env:
SOCI_CI_BACKEND: sqlite3
freebsd_instance:
image_family: freebsd-13-0
image_family: freebsd-13-2
install_script: ./scripts/ci/install.sh
before_build_script: ./scripts/ci/before_build.sh
build_script: ./scripts/ci/build.sh
Expand Down
16 changes: 15 additions & 1 deletion include/private/soci-mktime.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ namespace soci
namespace details
{

SOCI_DECL time_t timegm_impl_soci ( struct tm* tb );

template <typename T>
auto timegm_impl(T* t) -> decltype(timegm(t))
{
return timegm(t);
}

template <typename T>
auto timegm_impl(T t) -> time_t
{
return timegm_impl_soci(t);
}

// Fill the provided struct tm with the values corresponding to the given date
// in UTC.
//
Expand All @@ -40,7 +54,7 @@ mktime_from_ymdhms(tm& t,
t.tm_min = minute;
t.tm_sec = second;

timegm(&t);
timegm_impl(&t);
}

// Helper function for parsing datetime values.
Expand Down
48 changes: 48 additions & 0 deletions src/core/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,51 @@ void soci::details::parse_std_tm(char const * buf, std::tm & t)

mktime_from_ymdhms(t, year, month, day, hour, minute, second);
}


// https://stackoverflow.com/a/58037981/15275
namespace
{
// Algorithm: http://howardhinnant.github.io/date_algorithms.html
int days_from_epoch ( int y, int m, int d )
{
y -= m <= 2;
const int era = y / 400;
const int yoe = y - era * 400; // [0, 399]
const int doy = ( 153 * ( m + ( m > 2 ? -3 : 9 ) ) + 2 ) / 5 + d - 1; // [0, 365]
const int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
return era * 146097 + doe - 719468;
}
} // namespace

time_t soci::details::timegm_impl_soci ( struct tm* tb )
{
int year = tb->tm_year + 1900;
int month = tb->tm_mon; // 0-11

if ( month > 11 )
{
year += month / 12;
month %= 12;
}
else if ( month < 0 )
{
const int years_diff = ( 11 - month ) / 12;
year -= years_diff;
month += 12 * years_diff;
}
const int days_since_epoch = days_from_epoch ( year, month + 1, tb->tm_mday );

time_t since_epoch = 60 * ( 60 * ( 24L * days_since_epoch + tb->tm_hour ) + tb->tm_min ) + tb->tm_sec;

struct tm tmp;
#ifdef _WIN32
gmtime_s ( &tmp, &since_epoch );
#else
gmtime_r ( &since_epoch, &tmp );
#endif // _WIN32
*tb = tmp;

return since_epoch;
}

1 change: 1 addition & 0 deletions src/core/statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ void statement_impl::bind_clean_up()
delete indicators_[i];
indicators_[i] = NULL;
}
indicators_.clear();

row_ = NULL;
alreadyDescribed_ = false;
Expand Down
30 changes: 30 additions & 0 deletions tests/common-tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
#include <typeinfo>
#include <type_traits>

#include "soci-mktime.h"

// Although SQL standard mandates right padding CHAR(N) values to their length
// with spaces, some backends don't confirm to it:
//
Expand Down Expand Up @@ -614,6 +616,34 @@ using auto_table_creator = std::unique_ptr<table_creator_base>;
namespace test_cases
{

inline bool operator== ( const std::tm& a, const std::tm& b )
{
return a.tm_sec == b.tm_sec && a.tm_min == b.tm_min && a.tm_hour == b.tm_hour && a.tm_mday == b.tm_mday && a.tm_mon == b.tm_mon &&
a.tm_year == b.tm_year && a.tm_wday == b.tm_wday && a.tm_yday == b.tm_yday && a.tm_isdst == b.tm_isdst;
}

TEST_CASE_METHOD ( common_tests, "timegm implementation", "[core][timegm]" )
{
std::tm t1;
t1.tm_year = 105;
t1.tm_mon = 13; // + 1 year
t1.tm_mday = 15;
t1.tm_hour = 28; // + 1 day
t1.tm_min = 14;
t1.tm_sec = 17;

std::tm t2 = t1;

const auto timegm_result = timegm (&t1);
const auto timegm_soci_result = details::timegm_impl_soci (&t2);
CHECK ( timegm_result == timegm_soci_result );
CHECK ( t1.tm_year == 106 );
CHECK ( t1.tm_mon == 1 );
CHECK ( t1.tm_mday == 16 );
CHECK ( t1.tm_hour == 4 );
CHECK ( ( t1 == t2 ) );
}

TEST_CASE_METHOD(common_tests, "Exception on not connected", "[core][exception]")
{
soci::session sql; // no connection
Expand Down

0 comments on commit c4ff390

Please sign in to comment.