2025-12-12 04:09 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* include/harbour.hbx
  * src/harbour.def
  * src/rtl/dateshb.c
    + added new PRG function which converts UTC time to local time:
          hb_UTCToTS( <tUTCTime> [, @<lUTCOffset> ) -> <tLocalTime>

  * include/hbdate.h
  * src/harbour.def
  * src/common/hbdate.c
    + added new C function which converts UTC time to local time:
         double hb_timeUTCToLocal( double dTimeStamp, int * piUTCOffset );
This commit is contained in:
Przemysław Czerpak
2025-12-12 04:09:11 +01:00
parent f9212001b4
commit 5b05d5335d
6 changed files with 114 additions and 1 deletions

View File

@@ -7,6 +7,19 @@
Entries may not always be in chronological/commit order. Entries may not always be in chronological/commit order.
See license at the end of file. */ See license at the end of file. */
2025-12-12 04:09 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* include/harbour.hbx
* src/harbour.def
* src/rtl/dateshb.c
+ added new PRG function which converts UTC time to local time:
hb_UTCToTS( <tUTCTime> [, @<lUTCOffset> ) -> <tLocalTime>
* include/hbdate.h
* src/harbour.def
* src/common/hbdate.c
+ added new C function which converts UTC time to local time:
double hb_timeUTCToLocal( double dTimeStamp, int * piUTCOffset );
2025-12-11 00:15 UTC+0100 Aleksander Czajczynski (hb fki.pl) 2025-12-11 00:15 UTC+0100 Aleksander Czajczynski (hb fki.pl)
* src/vm/macro.c * src/vm/macro.c
* workaround MinGW/GCC 15+ excessive diagnostics in hb_macroTextSymbol() * workaround MinGW/GCC 15+ excessive diagnostics in hb_macroTextSymbol()

View File

@@ -922,6 +922,7 @@ DYNAMIC hb_UserName
DYNAMIC hb_UStuff DYNAMIC hb_UStuff
DYNAMIC hb_USubStr DYNAMIC hb_USubStr
DYNAMIC hb_UTCOffset DYNAMIC hb_UTCOffset
DYNAMIC hb_UTCToTS
DYNAMIC hb_utf8Asc DYNAMIC hb_utf8Asc
DYNAMIC hb_utf8At DYNAMIC hb_utf8At
DYNAMIC hb_utf8Chr DYNAMIC hb_utf8Chr

View File

@@ -104,6 +104,7 @@ extern HB_EXPORT void hb_timeStampGet( long * plJulian, long * plMilliSec );
extern HB_EXPORT long hb_timeUTCOffset( void ); /* in seconds */ extern HB_EXPORT long hb_timeUTCOffset( void ); /* in seconds */
extern HB_EXPORT double hb_timeLocalToUTC( double dTimeStamp ); extern HB_EXPORT double hb_timeLocalToUTC( double dTimeStamp );
extern HB_EXPORT double hb_timeUTCToLocal( double dTimeStamp, int * piUTCOffset );
extern HB_EXPORT long hb_timeStampUTCOffset( int iYear, int iMonth, int iDay, extern HB_EXPORT long hb_timeStampUTCOffset( int iYear, int iMonth, int iDay,
int iHour, int iMinutes, int iSeconds ); int iHour, int iMinutes, int iSeconds );

View File

@@ -495,7 +495,7 @@ char * hb_timeStr( char * szTime, long lMilliSec )
HB_BOOL hb_timeStrGetUTC( const char * szTime, HB_BOOL hb_timeStrGetUTC( const char * szTime,
int * piHour, int * piMinutes, int * piHour, int * piMinutes,
int * piSeconds, int * piMSec, int *piUTCOffset ) int * piSeconds, int * piMSec, int * piUTCOffset )
{ {
int iHour, iMinutes, iSeconds, iMSec, iUTCOffset, iBlocks; int iHour, iMinutes, iSeconds, iMSec, iUTCOffset, iBlocks;
HB_BOOL fValid; HB_BOOL fValid;
@@ -1180,6 +1180,86 @@ double hb_timeLocalToUTC( double dTimeStamp )
iHour, iMinutes, iSeconds ) / HB_SECONDS_PER_DAY; iHour, iMinutes, iSeconds ) / HB_SECONDS_PER_DAY;
} }
double hb_timeUTCToLocal( double dTimeStamp, int * piUTCOffset )
{
double dLocal;
#if defined( HB_OS_WIN )
{
typedef BOOL ( WINAPI * P_SYSTEMTIMETOTZSPECIFICLOCALTIME )( LPTIME_ZONE_INFORMATION, LPSYSTEMTIME, LPSYSTEMTIME );
static HB_BOOL s_fInit = HB_TRUE;
static P_SYSTEMTIMETOTZSPECIFICLOCALTIME s_pSystemTimeToTzSpecificLocalTime = NULL;
int iYear, iMonth, iDay, iHour, iMinutes, iSeconds, iMSec;
hb_timeStampUnpack( dTimeStamp,
&iYear, &iMonth, &iDay,
&iHour, &iMinutes, &iSeconds, &iMSec );
if( s_fInit )
{
HMODULE hModule = GetModuleHandle( TEXT( "kernel32" ) );
if( hModule )
s_pSystemTimeToTzSpecificLocalTime = ( P_SYSTEMTIMETOTZSPECIFICLOCALTIME )
HB_WINAPI_GETPROCADDRESS( hModule, "SystemTimeToTzSpecificLocalTime" );
s_fInit = HB_FALSE;
}
if( s_pSystemTimeToTzSpecificLocalTime )
{
SYSTEMTIME lt, st;
st.wYear = ( WORD ) iYear;
st.wMonth = ( WORD ) iMonth;
st.wDay = ( WORD ) iDay;
st.wHour = ( WORD ) iHour;
st.wMinute = ( WORD ) iMinutes;
st.wSecond = ( WORD ) iSeconds;
st.wMilliseconds = ( WORD ) iMSec;
st.wDayOfWeek = 0;
if( s_pSystemTimeToTzSpecificLocalTime( NULL, &st, &lt ) )
{
dLocal = hb_timeStampPack( lt.wYear, lt.wMonth, lt.wDay,
lt.wHour, lt.wMinute, lt.wSecond,
lt.wMilliseconds );
}
else
dLocal = dTimeStamp + ( double )
hb_timeStampUTCOffset( iYear, iMonth, iDay,
iHour, iMinutes, iSeconds ) / HB_SECONDS_PER_DAY;
}
else
dLocal = dTimeStamp + ( double )
hb_timeStampUTCOffset( iYear, iMonth, iDay,
iHour, iMinutes, iSeconds ) / HB_SECONDS_PER_DAY;
}
#else
{
long lJulian, lMilliSec;
struct tm lt;
time_t utc;
hb_timeStampUnpackDT( dTimeStamp, &lJulian, &lMilliSec );
utc = ( time_t ) ( ( lJulian - HB_SYS_DATE_BASE ) * HB_SECONDS_PER_DAY + lMilliSec / 1000 );
#if defined( HB_HAS_LOCALTIME_R )
localtime_r( &utc, &lt );
#else
lt = *localtime( &utc );
#endif
lJulian = hb_dateEncode( lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday );
lMilliSec = hb_timeEncode( lt.tm_hour, lt.tm_min, lt.tm_sec, lMilliSec % 1000 );
dLocal = hb_timeStampPackDT( lJulian, lMilliSec );
}
#endif
if( piUTCOffset )
*piUTCOffset = ( int ) ( ( dLocal - dTimeStamp ) * HB_SECONDS_PER_DAY +
( dLocal < dTimeStamp ? -0.5 : 0.5 ) );
return dLocal;
}
HB_MAXUINT hb_timerGet( void ) HB_MAXUINT hb_timerGet( void )
{ {
HB_TRACE( HB_TR_DEBUG, ( "hb_timerGet()" ) ); HB_TRACE( HB_TR_DEBUG, ( "hb_timerGet()" ) );

View File

@@ -1115,6 +1115,7 @@ HB_FUN_HB_USERNAME
HB_FUN_HB_USTUFF HB_FUN_HB_USTUFF
HB_FUN_HB_USUBSTR HB_FUN_HB_USUBSTR
HB_FUN_HB_UTCOFFSET HB_FUN_HB_UTCOFFSET
HB_FUN_HB_UTCTOTS
HB_FUN_HB_UTF8ASC HB_FUN_HB_UTF8ASC
HB_FUN_HB_UTF8AT HB_FUN_HB_UTF8AT
HB_FUN_HB_UTF8CHR HB_FUN_HB_UTF8CHR
@@ -3534,6 +3535,7 @@ hb_timeStrGet
hb_timeStrGetUTC hb_timeStrGetUTC
hb_timeStrRawGet hb_timeStrRawGet
hb_timeUTCOffset hb_timeUTCOffset
hb_timeUTCToLocal
hb_timeUnformat hb_timeUnformat
hb_timerGet hb_timerGet
hb_timerInit hb_timerInit

View File

@@ -586,6 +586,7 @@ HB_FUNC( HB_WEEK )
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
} }
/* hb_UTCOffset( [ <tLocalTime> ] ) -> <nSeconds> */
HB_FUNC( HB_UTCOFFSET ) HB_FUNC( HB_UTCOFFSET )
{ {
if( HB_ISDATETIME( 1 ) ) if( HB_ISDATETIME( 1 ) )
@@ -599,6 +600,7 @@ HB_FUNC( HB_UTCOFFSET )
hb_retnl( hb_timeUTCOffset() ); hb_retnl( hb_timeUTCOffset() );
} }
/* hb_TSToUTC( <tLocalTime> ) -> <tUTCTime> */
HB_FUNC( HB_TSTOUTC ) HB_FUNC( HB_TSTOUTC )
{ {
if( HB_ISTIMESTAMP( 1 ) ) if( HB_ISTIMESTAMP( 1 ) )
@@ -606,3 +608,17 @@ HB_FUNC( HB_TSTOUTC )
else else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
} }
/* hb_UTCToTS( <tUTCTime> [, @<lUTCOffset> ) -> <tLocalTime> */
HB_FUNC( HB_UTCTOTS )
{
if( HB_ISTIMESTAMP( 1 ) )
{
int iUTCOffset = 0;
hb_rettd( hb_timeUTCToLocal( hb_partd( 1 ), &iUTCOffset ) );
hb_storni( iUTCOffset, 2 );
}
else
hb_errRT_BASE_SubstR( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}