Obtaining Millisecond Server Time

johndanter

Legendary Poster
Hi folks,

I have an issue where I am trying to write the duration a transaction occurred and just use get start and end time BSFNs and work out the difference
Issue is, when it's really fast the difference is ZERO as the seconds are the same

So BSFN GetSystemUTime is not good enough as I need the millsecond element

IN->[ 5] <Item>: TimeDateStart <type>: JDEUTIME <Value>: [12/06/18 17:58:59 (UTC)] (actually Dec 6 11:58:59.116550 in the log)
IN->[ 6] <Item>: TimeDateEnd <type>: JDEUTIME <Value>: [12/06/18 17:58:59 (UTC)] (actually Dec 6 11:58:59.989770 in the log)

So this actually took 80000 nanoseconds but the overall second difference is ZERO

Any ideas folks? What DD items store milliseconds and what BSFNs can retrieve and store this. CPUS?
I can't see any BSFN on F9862

Thanks

John
 
Last edited:

BOster

Legendary Poster
If on windows (just need to find the equivalent for linux/as400):

Code:
/************************************************************************** 
 *  Business Function:  AcmeElapsedMillisecondsStart 
 * 
 *        Description:  AcmeElapsedMillisecondsStart 
 * 
 *         Parameters: 
 *           LPBHVRCOM           lpBhvrCom    Business Function Communications 
 *           LPVOID              lpVoid       Void Parameter - DO NOT USE! 
 *           LPDSD5800           lpDS         Parameter Data Structure Pointer   
 * 
 *************************************************************************/ 
 
JDEBFRTN (ID) JDEBFWINAPI AcmeElapsedMillisecondsStart (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD5800032A lpDS)  
 
{ 
   /************************************************************************ 
    *  Variable declarations 
    ************************************************************************/ 

   /************************************************************************ 
    * Check for NULL pointers 
    ************************************************************************/ 
   if ((lpBhvrCom == (LPBHVRCOM) NULL) || 
       (lpVoid    == (LPVOID)    NULL) || 
       (lpDS      == (LPDSD5800032A)	NULL)) 
   { 
     jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, _J("4363"), (LPVOID) NULL); 
     return ER_ERROR; 
   } 
 
   /************************************************************************ 
    * Main Processing 
    ************************************************************************/ 

	//lpDS->idPtrHndStartTime = timeGetTime();
	lpDS->idPtrHndStartTime = GetTickCount();
 
   /************************************************************************ 
    * Function Clean Up 
    ************************************************************************/ 
//FunctionCleanUp:

	return ER_SUCCESS;
} 


/************************************************************************** 
 *  Business Function:  AcmeElapsedMillisecondsEnd 
 * 
 *        Description:  AcmeElapsedMillisecondsEnd 
 * 
 *         Parameters: 
 *           LPBHVRCOM           lpBhvrCom    Business Function Communications 
 *           LPVOID              lpVoid       Void Parameter - DO NOT USE! 
 *           LPDSD5800           lpDS         Parameter Data Structure Pointer   
 * 
 *************************************************************************/ 
 
JDEBFRTN (ID) JDEBFWINAPI AcmeElapsedMillisecondsEnd (LPBHVRCOM lpBhvrCom, LPVOID lpVoid, LPDSD5800032B lpDS)  
 
{ 
   /************************************************************************ 
    *  Variable declarations 
    ************************************************************************/ 
	ID			endTime = 0, diff = 0;

   /************************************************************************ 
    * Check for NULL pointers 
    ************************************************************************/ 
   if ((lpBhvrCom == (LPBHVRCOM) NULL) || 
       (lpVoid    == (LPVOID)    NULL) || 
       (lpDS      == (LPDSD5800032B)	NULL)) 
   { 
     jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, _J("4363"), (LPVOID) NULL); 
     return ER_ERROR; 
   } 
 
   /************************************************************************ 
    * Main Processing 
    ************************************************************************/ 

	//endTime = timeGetTime();
	endTime = GetTickCount();

	if(lpDS->idPtrHndStartTime > endTime)
	{
		jdeErrorSet (lpBhvrCom, lpVoid, (ID) 0, _J("018Y"), (LPVOID) NULL); 
		return ER_ERROR; 
	}

	diff = endTime - lpDS->idPtrHndStartTime;
	LongToMathNumeric(diff, &lpDS->mnElapsedMilliseconds);


   /************************************************************************ 
    * Function Clean Up 
    ************************************************************************/ 
//FunctionCleanUp:

	return ER_SUCCESS;
}

I use this all the time and have some other complimentary functions to convert to hh:mm:ss, etc.

Btw, I name the parameter idPtrHndStartTime in the event I had some struct I need to store time in... perhaps on Linux???? If that was the case I could just jdeAlloc the struct, pass address via jdeStoreDataPtr, etc. When I went to implement on Windows it was just a DWORD so I stored the value directly in idPtrHndStartTime. All that to say, if you are on AS400 or Linux the implementation might not be as simple.

Oh.... and one other thing I may have to look at for JDE 64bit....
 
Last edited:

jileto

Well Known Member
Had the same problem recently. I used jdeGetDateTimeAndMilliSecCouter - that's not a typo, it really ends with "Couter". If you need an example, look at B9312
 

jdelisths

Reputable Poster
Confirmed that jdeGetDateTimeAndMilliSecCouter was introduced after 9.1.5x.

You can use clock_gettime in Unix. It is in time.h, which is included in JDE.h, but I am not sure if it was included specifically for Windows. If not you can include it in your business function.
 

Segfault

Reputable Poster
In the past, I've rolled my own:

Code:
#ifdef _WIN32
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
#include <time.h>

/* returns time in seconds since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC)
 * as a double, with fractional seconds as:
 * - Windows: 
 *      fractional microseconds (0.001 sec resolution)
 * - POSIX(UNIX/IBMi/etc): 
 *      fractional milliseconds (0.000001 sec resolution)
 */
double getTimeInSecDbl(void) 
{
# ifdef _WIN32
  struct _timeb tb;
  _ftime(&tb);
  return (double)tb.time + (0.001 * (double)tb.millitm);
# else
  struct timeval tv;
  /* Yes, I know,gettimeofday is deprecated since POSIX 2008.  
   * Convert to use clock_gettime() and nanoseconds on UNIX if you wish. */
  gettimeofday(&tv, 0); 
  return (double)tv.tv_sec + (0.000001 * (double)tv.tv_usec);
# endif
}

...And send the return value through DoubleToMathNumeric() to stick it into E1 data.

Note:
The real reason I used gettimeofday() is that the function clock_gettime() is only available if the macro _POSIX_TIMERS is defined in <unistd.h> to a value greater than 0 -- and it isn't available on all POSIX environments I work on (including some embedded ones) while gettimeofday() always seems to be present.
 
Last edited:
Top