void SG_time__format_local__i64(SG_context* pCtx, SG_int64 iTime, char * pBuf, SG_uint32 lenBuf) { // do simple formatting of time value and generate a localtime-based, human-readable time. // this is like ctime(3), asctime(3), gmtime(3), localtime(3) only i don't currently // care about all the various formatting options. // // that is, we don't care about: // [] which fields we show, // [] localization (which order we show the fields and month names), // [] 12 vs 24 hour time. // [] UTF8. // // we are given a buffer that must be SG_TIME_FORMAT_LENGTH+1 characters or larger. SG_time tm; SG_NULLARGCHECK_RETURN( pBuf ); SG_ARGCHECK_RETURN( (lenBuf >= SG_TIME_FORMAT_LENGTH+1), lenBuf ); // convert milliseconds-since-epoch into individual fields. SG_ERR_CHECK_RETURN( SG_time__decode__local(pCtx, iTime,&tm) ); SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, pBuf,lenBuf,"%04d/%02d/%02d %02d:%02d:%02d.%03d %+03d%02d", tm.year,tm.month,tm.mday, tm.hour,tm.min,tm.sec,tm.msec, tm.offsetUTC/3600,abs((tm.offsetUTC/60)%60)) ); }
void SG_workingdir__generate_and_create_temp_dir_for_purpose(SG_context * pCtx, const SG_pathname * pPathWorkingDirectoryTop, const char * pszPurpose, SG_pathname ** ppPathTempDir) { SG_pathname * pPathTempRoot = NULL; SG_pathname * pPath = NULL; SG_string * pString = NULL; SG_int64 iTimeUTC; SG_time tmLocal; SG_uint32 kAttempt = 0; SG_NONEMPTYCHECK_RETURN(pszPurpose); SG_NULLARGCHECK_RETURN(ppPathTempDir); // get path to "<wd-top>/.sgtemp". SG_ERR_CHECK( SG_workingdir__get_temp_path(pCtx,pPathWorkingDirectoryTop,&pPathTempRoot) ); SG_ERR_CHECK( SG_time__get_milliseconds_since_1970_utc(pCtx,&iTimeUTC) ); SG_ERR_CHECK( SG_time__decode__local(pCtx,iTimeUTC,&tmLocal) ); SG_ERR_CHECK( SG_STRING__ALLOC(pCtx,&pString) ); while (1) { // build path "<wd-top>/.sgtemp/<purpose>_20091201_0". // where <purpose> is something like "revert" or "merge". SG_ERR_CHECK( SG_string__sprintf(pCtx,pString,"%s_%04d%02d%02d_%d", pszPurpose, tmLocal.year,tmLocal.month,tmLocal.mday, kAttempt++) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx,&pPath,pPathTempRoot,SG_string__sz(pString)) ); // try to create a NEW temp directory. if this path already exists on disk, // loop and try again. if we have a hard errors, just give up. SG_fsobj__mkdir_recursive__pathname(pCtx,pPath); if (SG_context__has_err(pCtx) == SG_FALSE) goto success; if (SG_context__err_equals(pCtx,SG_ERR_DIR_ALREADY_EXISTS) == SG_FALSE) SG_ERR_RETHROW; SG_context__err_reset(pCtx); SG_PATHNAME_NULLFREE(pCtx,pPath); } success: *ppPathTempDir = pPath; SG_STRING_NULLFREE(pCtx, pString); SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot); return; fail: SG_STRING_NULLFREE(pCtx, pString); SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot); SG_PATHNAME_NULLFREE(pCtx, pPath); }
void SG_time__local_time(SG_context* pCtx, SG_time * pResult) { SG_int64 lMillisecondsSince1970; SG_ERR_CHECK( SG_time__get_milliseconds_since_1970_utc(pCtx, &lMillisecondsSince1970) ); SG_ERR_CHECK( SG_time__decode__local(pCtx, lMillisecondsSince1970, pResult) ); fail: return; }
void SG_time__format_local__i64_ns(SG_context* pCtx, SG_int64 iTime_ns, char * pBuf, SG_uint32 lenBuf) { SG_int64 iTime_ms = iTime_ns / 1000000; SG_int32 remainder = (SG_int32)(iTime_ns % 1000000); SG_time tm; SG_NULLARGCHECK_RETURN( pBuf ); SG_ARGCHECK_RETURN( (lenBuf >= SG_TIME_FORMAT_LENGTH+1), lenBuf ); // convert milliseconds-since-epoch into individual fields. SG_ERR_CHECK_RETURN( SG_time__decode__local(pCtx, iTime_ms, &tm) ); SG_ERR_CHECK_RETURN( SG_sprintf(pCtx, pBuf,lenBuf,"%04d/%02d/%02d %02d:%02d:%02d.%03d%06d %+03d%02d", tm.year,tm.month,tm.mday, tm.hour,tm.min,tm.sec,tm.msec,remainder, tm.offsetUTC/3600,abs((tm.offsetUTC/60)%60)) ); }