If you have time&date as a (continuous) number akin to *time_t*, you can simply use modulo to get full minutes (%60), hours, and so on.
In my experience, the values seem to be aligned with real time (modulo 60 occurs at full minute) but this is most likely not guaranteed anywhere.
Here is code to get what you want (with sub-second resolution):
/*
* Returns millisecond timing (in seconds) for the current time.
*
* Note: This function should be called once in single-threaded mode in Win32,
* to get it initialized.
*/
double now_secs(void) {
#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
/*
* Windows FILETIME values are "100-nanosecond intervals since
* January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as
* the offset and it seems, so would they:
*
* <http://msdn.microsoft.com/en-us/library/ms724928(VS.85).aspx>
*/
SYSTEMTIME st;
FILETIME ft;
ULARGE_INTEGER uli;
static ULARGE_INTEGER uli_epoch; // Jan 1st 1970 0:0:0
if (uli_epoch.HighPart==0) {
st.wYear= 1970;
st.wMonth= 1; // Jan
st.wDay= 1;
st.wHour= st.wMinute= st.wSecond= st.wMilliseconds= 0;
//
st.wDayOfWeek= 0; // ignored
if (!SystemTimeToFileTime( &st, &ft ))
FAIL( "SystemTimeToFileTime", GetLastError() );
uli_epoch.LowPart= ft.dwLowDateTime;
uli_epoch.HighPart= ft.dwHighDateTime;
}
GetSystemTime( &st ); // current system date/time in UTC
if (!SystemTimeToFileTime( &st, &ft ))
FAIL( "SystemTimeToFileTime", GetLastError() );
uli.LowPart= ft.dwLowDateTime;
uli.HighPart= ft.dwHighDateTime;
/* 'double' has less accuracy than 64-bit int, but if it were to degrade,
* it would do so gracefully. In practise, the integer accuracy is not
* of the 100ns class but just 1ms (Windows XP).
*/
return (double)(uli.QuadPart - uli_epoch.QuadPart) / 10000000.0;
#else
struct timeval tv;
// {
// time_t tv_sec; /* seconds since Jan. 1, 1970 */
// suseconds_t tv_usec; /* and microseconds */
// };
int rc= gettimeofday( &tv, NULL /*time zone not used any more (in Linux)*/ );
assert( rc==0 );
return ((double)tv.tv_sec) + ((tv.tv_usec)/1000) / 1000.0;
#endif
}