From b3ee8c65fb87348af14f52f1e0fadca9818eeb01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Thu, 23 Jan 2025 17:45:49 +0100 Subject: [PATCH] 2025-01-23 17:45 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * include/hbdate.h * src/common/hbdate.c * src/harbour.def + added new C functions: HB_BOOL hb_timeStrGetUTC( const char * szTime, int * piHour, int * piMinutes, int * piSeconds, int * piMSec, int * piUTCOffset ); HB_BOOL hb_timeStampStrGetUTC( const char * szDateTime, int * piYear, int * piMonth, int * piDay, int * piHour, int * piMinutes, int * piSeconds, int * piMSec, int * piUTCOffset ); They can decode timestamp value with ISO 8601 UTC offset. * src/common/hbdate.c * use hb_timeStampStrGetUTC() in hb_timeStampStrGetDT() and return UTC time if it was with UTC offset Now Harbour compiler accept timestamp strings with with UTC offset, i.e. ? t"2025-01-22 00:45 UTC+0100" // => 2025-01-21 23:45:00.000 Also HB_StrToTS() supports it. * src/pp/hbpp.c * use new hb_timeStampStrGetDT() to decode timestamp from ChangeLog to build revision number. It also fixes bug with decoding negative UTC offsets. --- ChangeLog.txt | 28 +++++++++++ include/hbdate.h | 14 ++++-- src/common/hbdate.c | 114 +++++++++++++++++++++++++++++++++++--------- src/harbour.def | 2 + src/pp/hbpp.c | 22 ++------- 5 files changed, 137 insertions(+), 43 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index f29e76e431..f111b9c49c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -7,6 +7,34 @@ Entries may not always be in chronological/commit order. See license at the end of file. */ +2025-01-23 17:45 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbdate.h + * src/common/hbdate.c + * src/harbour.def + + added new C functions: + HB_BOOL hb_timeStrGetUTC( const char * szTime, + int * piHour, int * piMinutes, + int * piSeconds, int * piMSec, + int * piUTCOffset ); + HB_BOOL hb_timeStampStrGetUTC( const char * szDateTime, + int * piYear, int * piMonth, + int * piDay, int * piHour, + int * piMinutes, int * piSeconds, + int * piMSec, int * piUTCOffset ); + They can decode timestamp value with ISO 8601 UTC offset. + + * src/common/hbdate.c + * use hb_timeStampStrGetUTC() in hb_timeStampStrGetDT() and return UTC + time if it was with UTC offset + Now Harbour compiler accept timestamp strings with with UTC offset, i.e. + ? t"2025-01-22 00:45 UTC+0100" // => 2025-01-21 23:45:00.000 + Also HB_StrToTS() supports it. + + * src/pp/hbpp.c + * use new hb_timeStampStrGetDT() to decode timestamp from ChangeLog to + build revision number. It also fixes bug with decoding negative UTC + offsets. + 2025-01-23 11:47 UTC+0100 Aleksander Czajczynski (hb fki.pl) * contrib/hbcurl/core.c * contrib/hbcurl/hbcurl.ch diff --git a/include/hbdate.h b/include/hbdate.h index 0f43909486..4267375633 100644 --- a/include/hbdate.h +++ b/include/hbdate.h @@ -88,7 +88,9 @@ extern HB_EXPORT char * hb_timeStr( char * szTime, long lMilliSec ); extern HB_EXPORT HB_BOOL hb_timeStrGet( const char * szTime, int * piHour, int * piMinutes, int * piSeconds, int * piMSec ); - +extern HB_EXPORT HB_BOOL hb_timeStrGetUTC( const char * szTime, + int * piHour, int * piMinutes, int * piSeconds, + int * piMSec, int * piUTCOffset ); extern HB_EXPORT void hb_timeStrRawGet( const char * szTime, int * piHour, int * piMinutes, int * piSeconds, int * piMSec ); @@ -110,9 +112,13 @@ extern HB_EXPORT void hb_timeStampStrRawGet( const char * szDateTime, long * p extern HB_EXPORT char * hb_timeStampStr( char * szDateTime, long lJulian, long lMilliSec ); extern HB_EXPORT HB_BOOL hb_timeStampStrGet( const char * szDateTime, - int * piYear, int * piMonth, int * piDay, - int * piHour, int * piMinutes, int * piSeconds, - int * piMSec ); + int * piYear, int * piMonth, int * piDay, + int * piHour, int * piMinutes, int * piSeconds, + int * piMSec ); +extern HB_EXPORT HB_BOOL hb_timeStampStrGetUTC( const char * szDateTime, + int * piYear, int * piMonth, int * piDay, + int * piHour, int * piMinutes, int * piSeconds, + int * piMSec, int * piUTCOffset ); extern HB_EXPORT HB_BOOL hb_timeStampStrGetDT( const char * szDateTime, long * plJulian, long * plMilliSec ); diff --git a/src/common/hbdate.c b/src/common/hbdate.c index 4e8c903e72..51ef993721 100644 --- a/src/common/hbdate.c +++ b/src/common/hbdate.c @@ -493,16 +493,16 @@ char * hb_timeStr( char * szTime, long lMilliSec ) return szTime; } -HB_BOOL hb_timeStrGet( const char * szTime, - int * piHour, int * piMinutes, - int * piSeconds, int * piMSec ) +HB_BOOL hb_timeStrGetUTC( const char * szTime, + int * piHour, int * piMinutes, + int * piSeconds, int * piMSec, int *piUTCOffset ) { - int iHour, iMinutes, iSeconds, iMSec, iBlocks; + int iHour, iMinutes, iSeconds, iMSec, iUTCOffset, iBlocks; HB_BOOL fValid; - HB_TRACE( HB_TR_DEBUG, ( "hb_timeStrGet(%s, %p, %p, %p, %p)", szTime, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_timeStrGetUTC(%s, %p, %p, %p, %p, %p)", szTime, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec, ( void * ) piUTCOffset ) ); - iHour = iMinutes = iSeconds = iMSec = iBlocks = 0; + iHour = iMinutes = iSeconds = iMSec = iUTCOffset = iBlocks = 0; fValid = HB_FALSE; if( szTime ) @@ -571,11 +571,41 @@ HB_BOOL hb_timeStrGet( const char * szTime, else if( iHour == 12 ) iHour = 0; } + else + { + if( HB_TOUPPER( szTime[ 0 ] ) == 'U' && + HB_TOUPPER( szTime[ 1 ] ) == 'T' && + HB_TOUPPER( szTime[ 2 ] ) == 'C' && + ( szTime[ 3 ] == '+' || szTime[ 3 ] == '-' ) ) + szTime += 3; + if( ( szTime[ 0 ] == '+' || szTime[ 0 ] == '-' ) && + HB_ISDIGIT( szTime[ 1 ] ) ) + { + HB_BOOL fMinus = ( szTime[ 0 ] == '-' ); + iUTCOffset = szTime[ 1 ] - '0'; + szTime += 2; + if( HB_ISDIGIT( *szTime ) ) + iUTCOffset = iUTCOffset * 10 + ( *szTime++ - '0' ); + iUTCOffset *= 60; + if( *szTime == ':' && HB_ISDIGIT( szTime[ 1 ] ) ) + ++szTime; + if( szTime[ 0 ] >= '0' && szTime[ 0 ] <= '5' && + HB_ISDIGIT( szTime[ 1 ] ) ) + { + iUTCOffset += ( szTime[ 0 ] - '0' ) * 10 + ( szTime[ 1 ] - '0' ); + szTime += 2; + } + iUTCOffset *= 60; + if( fMinus ) + iUTCOffset = -iUTCOffset; + } + } } while( HB_ISSPACE( *szTime ) ) ++szTime; if( *szTime == 0 && iBlocks > 0 && - iHour < 24 && iMinutes < 60 && iSeconds < 60 ) + iHour < 24 && iMinutes < 60 && iSeconds < 60 && + iUTCOffset >= -43200 && iUTCOffset <= 43200 ) fValid = HB_TRUE; else iHour = iMinutes = iSeconds = iMSec = 0; @@ -590,10 +620,22 @@ HB_BOOL hb_timeStrGet( const char * szTime, *piSeconds = iSeconds; if( piMSec ) *piMSec = iMSec; + if( piUTCOffset ) + *piUTCOffset = iUTCOffset; return fValid; } +HB_BOOL hb_timeStrGet( const char * szTime, + int * piHour, int * piMinutes, + int * piSeconds, int * piMSec ) +{ + HB_TRACE( HB_TR_DEBUG, ( "hb_timeStrGet(%s, %p, %p, %p, %p)", szTime, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec ) ); + + return hb_timeStrGetUTC( szTime, piHour, piMinutes, + piSeconds, piMSec, NULL ); +} + void hb_timeStrRawGet( const char * szTime, int * piHour, int * piMinutes, int * piSeconds, int * piMSec ) @@ -712,15 +754,15 @@ char * hb_timeStampStr( char * szDateTime, long lJulian, long lMilliSec ) return szDateTime; } -HB_BOOL hb_timeStampStrGet( const char * szDateTime, - int * piYear, int * piMonth, int * piDay, - int * piHour, int * piMinutes, int * piSeconds, - int * piMSec ) +HB_BOOL hb_timeStampStrGetUTC( const char * szDateTime, + int * piYear, int * piMonth, int * piDay, + int * piHour, int * piMinutes, int * piSeconds, + int * piMSec, int * piUTCOffset ) { int iYear, iMonth, iDay; HB_BOOL fValid; - HB_TRACE( HB_TR_DEBUG, ( "hb_timeStampStrGet(%s, %p, %p, %p, %p, %p, %p, %p)", szDateTime, ( void * ) piYear, ( void * ) piMonth, ( void * ) piDay, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_timeStampStrGetUTC(%s, %p, %p, %p, %p, %p, %p, %p, %p)", szDateTime, ( void * ) piYear, ( void * ) piMonth, ( void * ) piDay, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec, ( void * ) piUTCOffset ) ); iYear = iMonth = iDay = 0; fValid = HB_FALSE; @@ -816,15 +858,14 @@ HB_BOOL hb_timeStampStrGet( const char * szDateTime, } } - if( piHour || piMinutes || piSeconds || piMSec ) + if( piHour || piMinutes || piSeconds || piMSec || piUTCOffset || + ( ! fValid && szDateTime ) ) { - if( ! hb_timeStrGet( szDateTime, piHour, piMinutes, piSeconds, piMSec ) ) - { - if( szDateTime ) - fValid = HB_FALSE; - } - else + if( hb_timeStrGetUTC( szDateTime, piHour, piMinutes, piSeconds, + piMSec, piUTCOffset ) ) fValid = HB_TRUE; + else if( szDateTime ) + fValid = HB_FALSE; } else if( szDateTime ) fValid = HB_FALSE; @@ -839,21 +880,50 @@ HB_BOOL hb_timeStampStrGet( const char * szDateTime, return fValid; } +HB_BOOL hb_timeStampStrGet( const char * szDateTime, + int * piYear, int * piMonth, int * piDay, + int * piHour, int * piMinutes, int * piSeconds, + int * piMSec ) +{ + HB_TRACE( HB_TR_DEBUG, ( "hb_timeStampStrGet(%s, %p, %p, %p, %p, %p, %p, %p)", szDateTime, ( void * ) piYear, ( void * ) piMonth, ( void * ) piDay, ( void * ) piHour, ( void * ) piMinutes, ( void * ) piSeconds, ( void * ) piMSec ) ); + + return hb_timeStampStrGetUTC( szDateTime, piYear, piMonth, piDay, + piHour, piMinutes, piSeconds, + piMSec, NULL ); +} + HB_BOOL hb_timeStampStrGetDT( const char * szDateTime, long * plJulian, long * plMilliSec ) { - int iYear, iMonth, iDay, iHour, iMinutes, iSeconds, iMSec; + int iYear, iMonth, iDay, iHour, iMinutes, iSeconds, iMSec, iUTCOffset; HB_BOOL fValid; HB_TRACE( HB_TR_DEBUG, ( "hb_timeStampStrGetDT(%s, %p, %p)", szDateTime, ( void * ) plJulian, ( void * ) plMilliSec ) ); - fValid = hb_timeStampStrGet( szDateTime, &iYear, &iMonth, &iDay, - &iHour, &iMinutes, &iSeconds, &iMSec ); + fValid = hb_timeStampStrGetUTC( szDateTime, &iYear, &iMonth, &iDay, + &iHour, &iMinutes, &iSeconds, &iMSec, + &iUTCOffset ); if( plJulian ) *plJulian = hb_dateEncode( iYear, iMonth, iDay ); if( plMilliSec ) *plMilliSec = hb_timeEncode( iHour, iMinutes, iSeconds, iMSec ); + if( iUTCOffset != 0 && fValid ) + { + *plMilliSec -= iUTCOffset * 1000; + if( *plMilliSec < 0 ) + { + *plMilliSec += HB_MILLISECS_PER_DAY; + if( --( *plJulian ) < 0 ) + fValid = HB_FALSE; + } + else if( *plMilliSec >= HB_MILLISECS_PER_DAY ) + { + *plMilliSec -= HB_MILLISECS_PER_DAY; + ++( *plJulian ); + } + } + return fValid; } diff --git a/src/harbour.def b/src/harbour.def index 0e9d070c34..d4813b8f98 100644 --- a/src/harbour.def +++ b/src/harbour.def @@ -3514,6 +3514,7 @@ hb_timeStampPackDT hb_timeStampStr hb_timeStampStrGet hb_timeStampStrGetDT +hb_timeStampStrGetUTC hb_timeStampStrRawGet hb_timeStampStrRawPut hb_timeStampUTCOffset @@ -3523,6 +3524,7 @@ hb_timeStampUnpackD hb_timeStampUnpackDT hb_timeStr hb_timeStrGet +hb_timeStrGetUTC hb_timeStrRawGet hb_timeUTCOffset hb_timeUnformat diff --git a/src/pp/hbpp.c b/src/pp/hbpp.c index 03fbcadf29..34e0d493ce 100644 --- a/src/pp/hbpp.c +++ b/src/pp/hbpp.c @@ -594,27 +594,16 @@ static int hb_pp_parseChangelog( PHB_PP_STATE pState, const char * pszFileName, if( strlen( szLog ) >= 16 ) { long lJulian = 0, lMilliSec = 0; - int iUTC = 0; + int iLen = 16; - if( strlen( szLog ) >= 25 && szLog[ 17 ] == 'U' && + if( szLog[ 16 ] == ' ' && szLog[ 17 ] == 'U' && szLog[ 18 ] == 'T' && szLog[ 19 ] == 'C' && ( szLog[ 20 ] == '+' || szLog[ 20 ] == '-' ) && HB_ISDIGIT( szLog[ 21 ] ) && HB_ISDIGIT( szLog[ 22 ] ) && HB_ISDIGIT( szLog[ 23 ] ) && HB_ISDIGIT( szLog[ 24 ] ) ) - { - iUTC = ( ( int ) ( szLog[ 21 ] - '0' ) * 10 + - ( int ) ( szLog[ 22 ] - '0' ) ) * 60 + - ( int ) ( szLog[ 23 ] - '0' ) * 10 + - ( int ) ( szLog[ 24 ] - '0' ); - } - szLog[ 16 ] = '\0'; - if( iUTC != 0 && hb_timeStampStrGetDT( szLog, &lJulian, &lMilliSec ) ) - { - hb_timeStampUnpackDT( hb_timeStampPackDT( lJulian, lMilliSec ) - - ( double ) iUTC / ( 24 * 60 ), - &lJulian, &lMilliSec ); - } - if( lJulian && lMilliSec ) + iLen += 9; + szLog[ iLen ] = '\0'; + if( hb_timeStampStrGetDT( szLog, &lJulian, &lMilliSec ) ) { hb_timeStampStrRawPut( szRevID, lJulian, lMilliSec ); memmove( szRevID, szRevID + 2, 10 ); @@ -633,7 +622,6 @@ static int hb_pp_parseChangelog( PHB_PP_STATE pState, const char * pszFileName, szRevID[ 9 ] = szLog[ 15 ]; } szRevID[ 10 ] = '\0'; - } else szRevID[ 0 ] = '\0';