Skip to content

Commit

Permalink
Fixed date-time conversion (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
aregtech authored Aug 7, 2023
1 parent 54f7e54 commit 020516b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 83 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ name: CMake

on:
push: # Keep empty to run on each branch when push the code. Otherwise use branches: [ master ]
# pull_request: # Set to master to run only when merge with master branch
# branches: [ master ]
branches: [master]
pull_request: # Set to master to run only when merge with master branch
branches: [ master ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
Expand Down
4 changes: 2 additions & 2 deletions conf/cmake/user.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ endif()

# Build tests. By default it is disabled. To enable, set ON
if (NOT DEFINED AREG_BUILD_TESTS)
option(AREG_BUILD_TESTS "Build unit tests" ON)
option(AREG_BUILD_TESTS "Build unit tests" OFF)
endif()

# Build examples. By default it is disabled. To enable, set ON
Expand All @@ -163,7 +163,7 @@ endif()

# Set AREG extended features enable or disable flag to compiler additional optional features. By default, it is disabled.
if (NOT DEFINED AREG_EXTENDED)
option(AREG_EXTENDED "Enable extensions" ON)
option(AREG_EXTENDED "Enable extensions" OFF)
endif()

# Modify 'AREG_LOGS' to enable or disable compilation with logs. By default, compile with logs
Expand Down
10 changes: 4 additions & 6 deletions framework/areg/base/private/NEUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,13 @@ AREG_API_IMPL void NEUtilities::convToTm(const sSystemTime & IN sysTime, struct

AREG_API_IMPL void NEUtilities::makeTmLocal( struct tm & IN OUT utcTime )
{
NEMemory::memSet( &utcTime, sizeof( struct tm ), 0 );
time_t _timer = mktime( &utcTime );

#ifdef _WIN32
localtime_s( &utcTime, &_timer );
#else // _WIN32
struct tm * temp = localtime( &_timer );
if ( temp != nullptr )
{
NEMemory::memCopy( &utcTime, static_cast<unsigned int>(sizeof( tm )), temp, static_cast<unsigned int>(sizeof( tm )) );
}
localtime_r( &_timer, &utcTime );
#endif // _WIN32
}

Expand Down Expand Up @@ -292,4 +290,4 @@ AREG_API_IMPL NEUtilities::DataLiteral NEUtilities::convDuration( uint64_t timeD
}

return result;
}
}
127 changes: 60 additions & 67 deletions framework/areg/base/private/posix/NEUtilitiesPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@

namespace NEUtilities
{
/**
* \brief When converting the time in seconds to the time structure,
* we are loosing an information, so that we get a difference.
* With this method we compute the difference in seconds to balance.
* The method is only for internal use and should not be used outside
* of this file.
**/
inline int _internalTimeDifference( void )
{
struct timespec relTime;
::clock_gettime( CLOCK_REALTIME, &relTime );
time_t secs = static_cast<time_t>(relTime.tv_sec);

struct tm tmGmt{0};
gmtime_r(&secs, &tmGmt);
tmGmt.tm_isdst = -1;
time_t secsConv = std::mktime( &tmGmt );
int64_t timeDiff = static_cast<int64_t>(secs) - static_cast<int64_t>(secsConv);
return static_cast<int>(timeDiff);
}

/**
* \brief Generates a name, sets the timestamp of now.
Expand Down Expand Up @@ -71,7 +91,6 @@ namespace NEUtilities
outSecs = secs;
outMilli = static_cast<unsigned short>(rest / MILLISEC_TO_MICROSECS);
outMicro = static_cast<unsigned short>(rest % MILLISEC_TO_MICROSECS);

}


Expand All @@ -92,16 +111,16 @@ namespace NEUtilities
unsigned short milli, micro;
_convertMicrosecs( utcTime, secs, milli, micro );

struct tm * conv = ::localtime( &secs );
if ( conv != nullptr )
struct tm tmLocal{0};
if ( ::localtime_r( &secs, &tmLocal ) != nullptr )
{
localTime.stYear = conv->tm_year + 1900;
localTime.stMonth = conv->tm_mon + 1;
localTime.stDay = conv->tm_mday;
localTime.stHour = conv->tm_hour;
localTime.stMinute = conv->tm_min;
localTime.stSecond = conv->tm_sec;
localTime.stDayOfWeek = conv->tm_wday;
localTime.stYear = tmLocal.tm_year + 1900;
localTime.stMonth = tmLocal.tm_mon + 1;
localTime.stDay = tmLocal.tm_mday;
localTime.stHour = tmLocal.tm_hour;
localTime.stMinute = tmLocal.tm_min;
localTime.stSecond = tmLocal.tm_sec;
localTime.stDayOfWeek = tmLocal.tm_wday;
localTime.stMillisecs = milli;
localTime.stMicrosecs = micro;

Expand All @@ -113,41 +132,14 @@ namespace NEUtilities

bool _osConvToLocalTime( const sSystemTime & IN utcTime, sSystemTime & OUT localTime )
{
bool result = false;
TIME64 quad = NEUtilities::convToTime( utcTime );

// time_t secs = static_cast<time_t>(quad / SEC_TO_MICROSECS);
// time_t rest = quad - (secs * SEC_TO_MICROSECS);
// unsigned short milli = static_cast<unsigned short>(rest / MILLISEC_TO_MICROSECS);
// unsigned short micro = static_cast<unsigned short>(rest - (milli * MILLISEC_TO_MICROSECS));

time_t secs;
unsigned short milli, micro;
_convertMicrosecs( quad, secs, milli, micro );

struct tm * conv = ::localtime( &secs );
if ( conv != nullptr )
{
localTime.stYear = conv->tm_year + 1900;
localTime.stMonth = conv->tm_mon + 1;
localTime.stDay = conv->tm_mday;
localTime.stHour = conv->tm_hour;
localTime.stMinute = conv->tm_min;
localTime.stSecond = conv->tm_sec;
localTime.stDayOfWeek = conv->tm_wday;
localTime.stMillisecs = milli;
localTime.stMicrosecs = micro;

result = true;
}

return result;
return _osConvToLocalTime(quad, localTime);
}

void _osSystemTimeNow( NEUtilities::sSystemTime & OUT sysTime, bool localTime )
{
struct timespec ts;
struct tm now;
struct timespec ts { 0 };
struct tm now { 0 };

::clock_gettime( CLOCK_REALTIME, &ts );
if ( localTime )
Expand Down Expand Up @@ -178,12 +170,12 @@ namespace NEUtilities

void _osSystemTimeNow( NEUtilities::sFileTime & OUT fileTime, bool localTime )
{
struct timespec ts;
struct timespec ts { 0 };
::clock_gettime( CLOCK_REALTIME, &ts );

if ( localTime )
{
struct tm now;
struct tm now { 0 };
::localtime_r( &ts.tv_sec, &now );
time_t local = ::mktime( &now );
TIME64 quad = static_cast<TIME64>(local * SEC_TO_MICROSECS) + static_cast<TIME64>(ts.tv_nsec / MICROSEC_TO_NS);
Expand All @@ -200,31 +192,32 @@ namespace NEUtilities

TIME64 _osSystemTimeNow( void )
{
struct timespec ts;
struct timespec ts { 0 };
::clock_gettime( CLOCK_REALTIME, &ts );

TIME64 quad = ts.tv_sec * SEC_TO_MICROSECS + ts.tv_nsec / MICROSEC_TO_NS;
TIME64 quad = static_cast<TIME64>(ts.tv_sec) * SEC_TO_MICROSECS + static_cast<TIME64>(ts.tv_nsec) / MICROSEC_TO_NS;
return quad;
}

TIME64 _osConvToTime( const NEUtilities::sSystemTime & sysTime )
{
TIME64 quad = 0;

struct tm sys;
sys.tm_year = sysTime.stYear - 1900;
sys.tm_mon = sysTime.stMonth - 1;
sys.tm_mday = sysTime.stDay;
sys.tm_hour = sysTime.stHour;
sys.tm_min = sysTime.stMinute;
sys.tm_sec = sysTime.stSecond;
sys.tm_wday = sysTime.stDayOfWeek;
sys.tm_isdst = 0;

time_t secs = ::mktime( &sys );
struct tm tmSys;
tmSys.tm_year = sysTime.stYear - 1900;
tmSys.tm_mon = sysTime.stMonth - 1;
tmSys.tm_mday = sysTime.stDay;
tmSys.tm_hour = sysTime.stHour;
tmSys.tm_min = sysTime.stMinute;
tmSys.tm_sec = sysTime.stSecond;
tmSys.tm_isdst = -1;

time_t secs = std::mktime( &tmSys );
secs += _internalTimeDifference();

if ( secs != static_cast<time_t>(-1) )
{
quad = (secs * SEC_TO_MICROSECS) + (sysTime.stMillisecs * MILLISEC_TO_MICROSECS) + sysTime.stMicrosecs;
quad = (SEC_TO_MICROSECS * secs) + (MILLISEC_TO_MICROSECS * sysTime.stMillisecs) + sysTime.stMicrosecs;
}

return quad;
Expand All @@ -239,20 +232,20 @@ namespace NEUtilities
// unsigned short milli = static_cast<unsigned short>(rest / MILLISEC_TO_MICROSECS);
// unsigned short micro = static_cast<unsigned short>(rest - (milli * MILLISEC_TO_MICROSECS));

time_t secs;
unsigned short milli, micro;
time_t secs{ 0 };
unsigned short milli{ 0 }, micro{ 0 };
_convertMicrosecs( timeValue, secs, milli, micro );

struct tm * conv = ::gmtime( &secs );
if ( conv != nullptr )
struct tm utc{ 0 };
if ( ::gmtime_r( &secs, &utc ) != nullptr )
{
sysTime.stYear = conv->tm_year + 1900;
sysTime.stMonth = conv->tm_mon + 1;
sysTime.stDay = conv->tm_mday;
sysTime.stHour = conv->tm_hour;
sysTime.stMinute = conv->tm_min;
sysTime.stSecond = conv->tm_sec;
sysTime.stDayOfWeek = conv->tm_wday;
sysTime.stYear = utc.tm_year + 1900;
sysTime.stMonth = utc.tm_mon + 1;
sysTime.stDay = utc.tm_mday;
sysTime.stHour = utc.tm_hour;
sysTime.stMinute = utc.tm_min;
sysTime.stSecond = utc.tm_sec;
sysTime.stDayOfWeek = utc.tm_wday;
sysTime.stMillisecs = milli;
sysTime.stMicrosecs = micro;
}
Expand Down
7 changes: 1 addition & 6 deletions tests/units/DateTimeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,14 @@ TEST( DateTimeTest, TestLocalTime )
NEUtilities::convToLocalTime( utcTime, localTime );
_checkTimeStruct( localTime, "Areg Local " );

struct tm conv { 0 };
NEUtilities::convToTm( localTime, conv );

_checkTimeStruct( conv, "struct tm Local " );

NEUtilities::sSystemTime sysTime;
NEUtilities::convToLocalTime( date.getTime( ), sysTime );

ASSERT_EQ( localTime.stYear, sysTime.stYear ) << "localTime.stYear = " << localTime.stYear << ", sysTime.stYear = " << sysTime.stYear << std::endl;
ASSERT_EQ( localTime.stMonth, sysTime.stMonth ) << "localTime.stMonth= " << localTime.stMonth << ", sysTime.stMonth = " << sysTime.stMonth << std::endl;
ASSERT_EQ( localTime.stDay, sysTime.stDay ) << "localTime.stDay = " << localTime.stDay << ", sysTime.stDay = " << sysTime.stDay << std::endl;
ASSERT_EQ( localTime.stDayOfWeek, sysTime.stDayOfWeek ) << "localTime.stDayOfWeek = " << localTime.stDayOfWeek << ", sysTime.stDayOfWeek = " << sysTime.stDayOfWeek << std::endl;
// ASSERT_EQ( localTime.stHour, sysTime.stHour ) << "localTime.stHour = " << localTime.stHour << ", sysTime.stHour = " << sysTime.stHour << std::endl;
ASSERT_EQ( localTime.stHour, sysTime.stHour ) << "localTime.stHour = " << localTime.stHour << ", sysTime.stHour = " << sysTime.stHour << std::endl;
ASSERT_EQ( localTime.stMinute, sysTime.stMinute ) << "localTime.stMinute = " << localTime.stMinute << ", sysTime.stMinute = " << sysTime.stMinute << std::endl;
ASSERT_EQ( localTime.stSecond, sysTime.stSecond ) << "localTime.stSecond = " << localTime.stSecond << ", sysTime.stSecond = " << sysTime.stSecond << std::endl;
ASSERT_EQ( localTime.stMillisecs, sysTime.stMillisecs ) << "localTime.stMillisecs = " << localTime.stMillisecs << ", sysTime.stMillisecs = " << sysTime.stMillisecs << std::endl;
Expand Down

0 comments on commit 020516b

Please sign in to comment.