Ejemplo n.º 1
0
const char_t* micro_time::format(char_t* buffer, uint64_t time) {

  const char_t kStartNumber = (char_t)('0');
  //
  uint64_t milli_sec = to_millisecond(time);
  uint64_t sec = milli_sec / 1000;
  milli_sec = milli_sec % 1000;
  time_t now = m_gStartTime_std + sec;

  struct tm today;
  LOCALTIME(today, now);

  /* store tens of hour */
  buffer[0] = (char_t)(today.tm_hour    / 10 + kStartNumber);
  /* store units of hour */
  buffer[1] = (char_t)(today.tm_hour   % 10 + kStartNumber);
  /* store tens of minute */
  buffer[2]= (char_t)(today.tm_min     / 10 + kStartNumber);
  /* store units of minute */
  buffer[3]= (char_t)(today.tm_min     % 10 + kStartNumber);
  /* store tens of second */
  buffer[4]= (char_t)(today.tm_sec     / 10 + kStartNumber);
  /* store units of second */
  buffer[5]= (char_t)(today.tm_sec     % 10 + kStartNumber);

  // millisecond
  buffer[6]= (char_t)('.');
  buffer[7]= (char_t)(milli_sec        / 1000 + kStartNumber);
  buffer[8]= (char_t)((milli_sec/ 100) % 10 + kStartNumber);
  buffer[9]= (char_t)(milli_sec        % 10 + kStartNumber);

  // XXX
  buffer[10] = 0;
  return buffer;
}
Ejemplo n.º 2
0
void vcmosRefresh()
{
	static time_t tprev = 0;
	time_t tcurr;
	struct tm *ptm;
	t_nubit8 century,year,month,mday,wday,hour,min,sec;

	tcurr = time(NULL);
	if (tcurr == tprev) return;
	else tprev = tcurr;
	ptm = LOCALTIME(&tcurr);

	century = (t_nubit8)(19 + ptm->tm_year / 100);
	year    = (t_nubit8)(ptm->tm_year % 100);
	month   = (t_nubit8)(ptm->tm_mon + 0x01);
	mday    = (t_nubit8)(ptm->tm_mday);
	wday    = (t_nubit8)(ptm->tm_wday + 0x01);
	hour    = (t_nubit8)(ptm->tm_hour);
	min     = (t_nubit8)(ptm->tm_min);
	sec     = (t_nubit8)(ptm->tm_sec);

	vcmos.reg[VCMOS_RTC_SECOND]    = Hex2BCD(sec);
	vcmos.reg[VCMOS_RTC_MINUTE]    = Hex2BCD(min);
	vcmos.reg[VCMOS_RTC_HOUR]      = Hex2BCD(hour);
	vcmos.reg[VCMOS_RTC_DAY_WEEK]  = Hex2BCD(wday);
	vcmos.reg[VCMOS_RTC_DAY_MONTH] = Hex2BCD(mday);
	vcmos.reg[VCMOS_RTC_MONTH]     = Hex2BCD(month);
	vcmos.reg[VCMOS_RTC_YEAR]      = Hex2BCD(year);
	vcmos.reg[VCMOS_RTC_CENTURY]   = Hex2BCD(century);
}
Ejemplo n.º 3
0
void
rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
    struct tm tm;
    time_t s = sec;
    LOCALTIME(&s, &tm);

    const char* zone = NULL;
#if defined(__WIN32__)
    int32_t gmtoff = -timezone;
    wchar_t wbuffer[64] = {0};
    char buffer[256] = {0};
    // strftime("%Z") can contain non-UTF-8 characters on non-English locale (issue #9418),
    // so time zone should be converted from UTF-16 string.
    // Since wcsftime depends on setlocale() result,
    // instead we convert it using MultiByteToWideChar.
    if (strftime(buffer, sizeof(buffer) / sizeof(char), "%Z", &tm) > 0) {
        // ANSI -> UTF-16
        MultiByteToWideChar(CP_ACP, 0, buffer, -1, wbuffer, sizeof(wbuffer) / sizeof(wchar_t));
        // UTF-16 -> UTF-8
        WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL);
        zone = buffer;
    }
#else
    int32_t gmtoff = tm.tm_gmtoff;
    zone = tm.tm_zone;
#endif

    tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec);
}
Ejemplo n.º 4
0
static const char* VisualCppTimeString()
{
    time_t the_time = time(NULL);
    struct tm the_local_time;
    static char dateTime[80];
    LOCALTIME(&the_local_time, &the_time);
    strftime(dateTime, 80, "%Y-%m-%dT%H:%M:%S", &the_local_time);
    return dateTime;
}
Ejemplo n.º 5
0
// millisecond 
const char_t* micro_time::format_with_ymd(char_t* buffer, uint64_t time) {
  
  const char_t kStartNumber = (char_t)('0');
  //
  uint64_t milli_sec = to_millisecond(time);
  uint64_t sec = milli_sec / 1000;
  milli_sec = milli_sec % 1000;
  time_t now = m_gStartTime_std + sec;

  struct tm today;
  LOCALTIME(today, now);
  // XXX
  int year = today.tm_year + 1900;
  int month = today.tm_mon + 1;

  /* store thousands of year */
  buffer[0] = (char_t)(year             / 1000 + kStartNumber);
  /* store hundreds of year */
  buffer[1] = (char_t)((year/ 100)      % 10 + kStartNumber);
  /* store tens of year */
  buffer[2] = (char_t)((year/ 10)       % 10 + kStartNumber);
  /* store units of year */
  buffer[3] = (char_t)(year             % 10 + kStartNumber);
  /* store tens of month */
  buffer[4] = (char_t)(month            / 10 + kStartNumber);
  /* store units of month */
  buffer[5] = (char_t)(month            % 10 + kStartNumber);
  /* store tens of day */
  buffer[6] = (char_t)(today.tm_mday    / 10 + kStartNumber);
  /* store units of day */
  buffer[7] = (char_t)(today.tm_mday    % 10 + kStartNumber);

  buffer[8] = (char_t)('-');

  /* store tens of hour */
  buffer[9] = (char_t)(today.tm_hour    / 10 + kStartNumber);
  /* store units of hour */
  buffer[10] = (char_t)(today.tm_hour   % 10 + kStartNumber);
  /* store tens of minute */
  buffer[11]= (char_t)(today.tm_min     / 10 + kStartNumber);
  /* store units of minute */
  buffer[12]= (char_t)(today.tm_min     % 10 + kStartNumber);
  /* store tens of second */
  buffer[13]= (char_t)(today.tm_sec     / 10 + kStartNumber);
  /* store units of second */
  buffer[14]= (char_t)(today.tm_sec     % 10 + kStartNumber);

  // millisecond
  buffer[15]= (char_t)('.');
  buffer[16]= (char_t)(milli_sec        / 1000 + kStartNumber);
  buffer[17]= (char_t)((milli_sec/ 100) % 10 + kStartNumber);
  buffer[18]= (char_t)(milli_sec        % 10 + kStartNumber);

  // XXX
  buffer[19] = 0;
  return buffer;
}
Ejemplo n.º 6
0
uint32_t DayTime::day_sec(uint32_t time_sec) {

  time_t now = (time_t)time_sec;
  struct tm today;
  LOCALTIME(today, now);

  return today.tm_hour * 60 * 60
    + today.tm_min * 60
    + today.tm_sec;
}
Ejemplo n.º 7
0
uint32_t DayTime::to_string(uint32_t sec) {

  //time_t now = micro_time::m_gStartTime_std + sec;
  time_t now = sec;
  struct tm today;
  LOCALTIME(today, now);

  return today.tm_hour * 10000 
    + today.tm_min * 100
    + today.tm_sec;
}
Ejemplo n.º 8
0
uint32_t DayTime::to_string(uint64_t time) {

  uint64_t milli_sec = micro_time::to_millisecond(time);
  uint64_t sec = milli_sec / 1000;
  time_t now = micro_time::m_gStartTime_std + sec;

  struct tm today;
  LOCALTIME(today, now);

  return today.tm_hour * 10000 
    + today.tm_min * 100
    + today.tm_sec;
}
Ejemplo n.º 9
0
void
rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
    struct tm tm;
    time_t s = sec;
    LOCALTIME(&s, &tm);

#if defined(__WIN32__)
    int32_t gmtoff = -timezone;
#else
    int32_t gmtoff = tm.tm_gmtoff;
#endif

    tm_to_rust_tm(&tm, timeptr, gmtoff, nsec);
}
Ejemplo n.º 10
0
extern "C" CDECL void
rust_localtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) {
    tm tm;
    time_t s = *sec;
    LOCALTIME(&s, &tm);

#if defined(__WIN32__)
    int32_t gmtoff = -timezone;
    char zone[64];
    strftime(zone, sizeof(zone), "%Z", &tm);
#else
    int32_t gmtoff = tm.tm_gmtoff;
    const char *zone = tm.tm_zone;
#endif

    tm_to_rust_tm(&tm, timeptr, gmtoff, zone, *nsec);
}
Ejemplo n.º 11
0
int32_t
rust_time_localtime(int64_t sec, int32_t nsec, rust_time_tm *timeptr) {
    struct tm tm;
    time_t s = sec;
    if (LOCALTIME(&s, &tm) == NULL) { return 0; }

#if defined(__WIN32__)
    int32_t utcoff = -timezone;
#elif defined(__native_client__)
    int32_t utcoff = _timezone;
#else
    int32_t utcoff = tm.tm_gmtoff;
#endif

    tm_to_rust_tm(&tm, timeptr, utcoff, nsec);
    return 1;
}
Ejemplo n.º 12
0
bool_t DayTime::get_localtime(uint32_t* year, uint32_t* mon, uint32_t* day
                              , uint32_t* hour, uint32_t* min, uint32_t* sec
                              , uint32_t srcTime) {

  /* */
  time_t now = srcTime;
  struct tm today;
  LOCALTIME(today, now);
  
  if (year) { *(year) = today.tm_year + 1900; }
  if (mon)  { *(mon)  = today.tm_mon + 1; }
  if (day)  { *(day)  = today.tm_mday; }

  if (hour) { *(hour) = today.tm_hour; }
  if (min)  { *(min)  = today.tm_min; }
  if (sec)  { *(sec)  = today.tm_sec; }

  return TRUE;
}
Ejemplo n.º 13
0
/*! 
 *************************************************************************************
 * \brief	System trace log output in Wels
 *
 * \param	pCtx	instance pointer
 * \param	kiLevel	log iLevel ( WELS_LOG_QUIET, ERROR, WARNING, INFO, DEBUG )
 * \param	kpFmtStr	formated string to mount
 * \param 	argv	pData string argument
 *
 * \return	NONE
 *
 * \note	N/A
 *************************************************************************************
 */
void WelsLogDefault( void *pCtx, const int32_t kiLevel, const str_t *kpFmtStr, va_list argv )
{
	sWelsEncCtx *pEncCtx	= (sWelsEncCtx *)pCtx;
	iWelsLogLevel		 iVal	= (kiLevel & g_iLevelLog);

	if ( 0 == iVal || NULL == pEncCtx )	// such iLevel not enabled
	{
		return;
	}
	else
	{
		str_t pBuf[WELS_LOG_BUF_SIZE+1] = {0};		
		const int32_t kiBufSize = sizeof(pBuf) / sizeof(pBuf[0]) - 1;
		int32_t iCurUsed = 0;
		int32_t iBufUsed = 0;
		int32_t iBufLeft = kiBufSize - iBufUsed;
		
		if ( pEncCtx ){
			time_t l_time;
#if defined(WIN32)
#if defined(_MSC_VER)
#if _MSC_VER >= 1500
			struct tm t_now;
#else//VC6
			struct tm* t_now;
#endif//_MSC_VER >= 1500
#endif//_MSC_VER
#else//__GNUC__
			struct tm* t_now;
#endif//WIN32			
			
#if defined( WIN32 )
			struct _timeb tb;
			
			time(&l_time);
#ifdef _MSC_VER
#if _MSC_VER >= 1500
			LOCALTIME(&t_now, &l_time);
#else
			t_now = LOCALTIME(&l_time);
			if ( NULL == t_now )
			{
				return;
			}
#endif//_MSC_VER >= 1500
#endif//_MSC_VER			
			FTIME(&tb);
#elif defined( __GNUC__ )
			struct timeval tv;
			time(&l_time);
			t_now = (struct tm *)LOCALTIME(&l_time);
			gettimeofday(&tv,NULL);
#endif//WIN32
			if (iBufLeft > 0){
#ifdef _MSC_VER
#if _MSC_VER >= 1500
				iCurUsed = SNPRINTF( &pBuf[iBufUsed], iBufLeft, iBufLeft, "[0x%p @ ", pEncCtx );	// confirmed_safe_unsafe_usage
#else
				iCurUsed = SNPRINTF( &pBuf[iBufUsed], iBufLeft, "[0x%p @ ", pEncCtx );	// confirmed_safe_unsafe_usage
#endif//_MSC_VER >= 1500
#endif//_MSC_VER
				if (iCurUsed >= 0){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}				
			}
			else{
				return;
			}

			if ( iBufLeft > 0 ){			
				iCurUsed = GetCodeName( &pBuf[iBufUsed], iBufLeft );
				if ( iCurUsed > 0 ){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}
				pBuf[iBufUsed] = ' ';
				++ iBufUsed;
				-- iBufLeft;
				
				iCurUsed = GetLibName( &pBuf[iBufUsed], iBufLeft );
				if ( iCurUsed > 0 ){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}
				pBuf[iBufUsed] = ' ';
				++ iBufUsed;
				-- iBufLeft;

				pBuf[iBufUsed] = 'v';
				++ iBufUsed;
				-- iBufLeft;		
				iCurUsed = GetVerNum( &pBuf[iBufUsed], iBufLeft );
				if ( iCurUsed > 0 ){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}
				pBuf[iBufUsed] = ' ';
				++ iBufUsed;
				-- iBufLeft;				
			}

			if (iBufLeft > 0){
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1500)
				iCurUsed = strftime(&pBuf[iBufUsed], iBufLeft, "%y-%m-%d %H:%M:%S", &t_now);
#else
				iCurUsed = strftime(&pBuf[iBufUsed], iBufLeft, "%y-%m-%d %H:%M:%S", t_now);
#endif//WIN32..
				if (iCurUsed > 0){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}
			}
			else{
				return;
			}

			if (iBufLeft > 0){
#if defined (WIN32)
#ifdef _MSC_VER
#if _MSC_VER >= 1500
				iCurUsed = SNPRINTF(&pBuf[iBufUsed], iBufLeft, iBufLeft, ".%03.3u]: ", tb.millitm);	// confirmed_safe_unsafe_usage
#else
				iCurUsed = SNPRINTF(&pBuf[iBufUsed], iBufLeft, ".%3.3u]: ", tb.millitm);	// confirmed_safe_unsafe_usage
#endif//_MSC_VER >= 1500
#endif//_MSC_VER
#elif defined (__GNUC__)
				iCurUsed = SNPRINTF(&pBuf[iBufUsed], iBufLeft, ".%3.3u]: ", tv.tv_usec/1000);	// confirmed_safe_unsafe_usage
#endif//WIN32
				if (iCurUsed >= 0){
					iBufUsed += iCurUsed;
					iBufLeft -= iCurUsed;
				}
			}
			else{
				return;
			}
		}

		// fixed stack corruption issue on vs2008
		if ( iBufLeft > 0 ){
			int32_t i_shift = 0;			
			str_t *pStr = NULL;
			pStr	= GetLogTag( kiLevel, &i_shift );
			if ( NULL != pCtx){
				int32_t iLenTag = STRNLEN( pStr, 8 );	// confirmed_safe_unsafe_usage
				STRCAT( &pBuf[iBufUsed], iBufLeft, pStr );	// confirmed_safe_unsafe_usage
				iBufUsed += iLenTag;
				pBuf[iBufUsed] = ' ';
				iBufUsed++;
				++iLenTag;
				iBufLeft -= iLenTag;
			}			
		}
		if (iBufLeft > 0){
#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1500)
			int32_t len = 0;
			len = _vscprintf( kpFmtStr, argv ) // _vscprintf doesn't count
					+ 1; // terminating '\0'
			iCurUsed = VSPRINTF(&pBuf[iBufUsed], len, kpFmtStr, argv);	// confirmed_safe_unsafe_usage
#else
			iCurUsed = VSPRINTF(&pBuf[iBufUsed], kpFmtStr, argv);	// confirmed_safe_unsafe_usage
#endif//WIN32..
			if (iCurUsed > 0){
				iBufUsed += iCurUsed;
				iBufLeft -= iCurUsed;
			}
		}
#ifdef ENABLE_TRACE_FILE
		if (NULL != pEncCtx && NULL != pEncCtx->pFileLog){
			if ( pEncCtx->uiSizeLog > MAX_TRACE_LOG_SIZE){
				if (0 == fseek(pEncCtx->pFileLog, 0L, SEEK_SET))
					pEncCtx->uiSizeLog = 0;
			}
			if ( iBufUsed > 0 && iBufUsed < WELS_LOG_BUF_SIZE )
			{
				iCurUsed = fwrite(pBuf, 1, iBufUsed, pEncCtx->pFileLog);
				fflush( pEncCtx->pFileLog );
				if ( iCurUsed == iBufUsed )
					pEncCtx->uiSizeLog += iBufUsed;
			}			
		}
		else{
#if defined(WIN32) && defined(_DEBUG)
			OutputDebugStringA(pBuf);
#endif
		}
#endif//ENABLE_TRACE_FILE
	}	
}
Ejemplo n.º 14
0
bool_t FileCollectorImpl::searchAllFile(collector_log_type_e collector_log_type
                                        ,CollectRule* pCollectRule, file_collect_callback_t pfn_cb, void* context) {

  ASSERT(pCollectRule);
  ASSERT(pfn_cb);

  // now
  struct tm today;
  time_t now = time(NULL);
  LOCALTIME(today, now);

  WIN32_FIND_DATA find_file_data;

  //__try 
  {

    HANDLE find_handle = FindFirstFile(pCollectRule->find_dir, &find_file_data);

    if (find_handle != INVALID_HANDLE_VALUE) {
      do {
        // Don't count current or parent directories.
        if ((STRCMP(find_file_data.cFileName, _STR("..")) == 0) ||
          (STRCMP(find_file_data.cFileName, _STR(".")) == 0))
          continue;

        if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; }

        /*
        long result = CompareFileTime(&find_file_data.ftCreationTime,  // NOLINT
          &comparison_filetime);
        // File was created after or on comparison time
        if ((result == 1) || (result == 0))
          ++file_count;
        */

        // is we need file
        //uint32_t nMatchLen = STRLEN(find_file_data.cFileName);
        if (TRUE == pCollectRule->regExExclude.didCompile()
          && TRUE == pCollectRule->regExExclude.isMatchOnly(find_file_data.cFileName)
        ) { continue; }

        if (FALSE == pCollectRule->regExInclude.isMatchOnly(find_file_data.cFileName)) { continue; }

        // test file
//         char_t strPath[MAX_PATH + 1] = {0};
//         SNPRINTF(strPath, MAX_PATH, MAX_PATH, "%s/%s", pCollectRule->dir, find_file_data.cFileName);
//         AutoReleaseFile autoRelFile(OpenFile(strPath, strAttrOpenRead));
//         if (NULL == autoRelFile) { continue; }

        // find map
        FileNode* pFileNode;
        if (MEM_NINI_LOG == collector_log_type) {
          pFileNode = findFileNode(pCollectRule->mml_hash, find_file_data.cFileName);
        }
        else {
          pFileNode = findFileNode(pCollectRule->hash, find_file_data.cFileName);
        }
        if (NULL == pFileNode) {

          if (TRUE == m_bAfterToDay) {
          // time control
          SYSTEMTIME nCreateTime;
          SYSTEMTIME stUTC;
          if (FALSE == FileTimeToSystemTime(&(find_file_data.ftCreationTime), &stUTC)
            || FALSE == SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &nCreateTime)
            ) { continue; }

          if (nCreateTime.wYear != today.tm_year + 1900
            || nCreateTime.wMonth != today.tm_mon + 1
            || nCreateTime.wDay != today.tm_mday
            ) { continue; }
          }


//           char_t strPath[MAX_PATH + 1] = {0};
//           SNPRINTF(strPath, MAX_PATH, MAX_PATH, "%s/%s", pCollectRule->dir, find_file_data.cFileName);

//           AutoReleaseFile AutoRelFile(::OpenFile(strPath, strAttrOpenRead));
//           if (NULL == AutoRelFile) { continue; }
// 
          pFileNode = new FileNode(pCollectRule->dir
            , MEM_NINI_LOG == collector_log_type ? pCollectRule->GetMMLDir() : NULL
            , find_file_data.cFileName);
          if (NULL == pFileNode) { continue; }

          // update file info
          FindData2FileInfo(&pFileNode->FileInfo(), find_file_data);

          // add to map
          addFileNode(pCollectRule->hash, pFileNode->LocalName(), pFileNode);

          // new file
          if (RC_S_OK != (pfn_cb)(/*this, */pFileNode, context)) { break; }
        }
        else {

          ASSERT(pFileNode);

          // update file info
          PlatformFileInfo& fileInfo = pFileNode->FileInfo();
          FindData2FileInfo(&fileInfo, find_file_data);

          if (pFileNode->GetSendSize() < fileInfo.size) {

            // new data
            if (RC_S_OK != (pfn_cb)(/*this, */pFileNode, context)) { break; }
          }
        }

      } while (FindNextFile(find_handle,  &find_file_data));

      FindClose(find_handle);
    }
  }
//    __except(EXCEPTION_EXECUTE_HANDLER) {
// 
//     return TRUE;
//   }

  return TRUE;
}
Ejemplo n.º 15
0
/** Converts a GMT timestamp to local datetime struct
	Adjusts to TZ if possible
 **/
int local_datetime(TIMESTAMP ts, DATETIME *dt)
{

	int64 n;
	TIMESTAMP rem = 0;
	TIMESTAMP local;
	int tsyear;

#ifdef USE_TS_CACHE
	/* allow caching */
	static TIMESTAMP old_ts =0;
	static DATETIME old_dt;
#endif

	if( ts == TS_NEVER || ts==TS_ZERO )
		return 0;

	if( dt==NULL || ts<TS_ZERO || ts>TS_MAX ) /* no buffer or timestamp out of range */
	{
		output_error("local_datetime(ts=%lli,...): invalid local_datetime request",ts);
		return 0;
	}
#ifdef USE_TS_CACHE
	/* check cache */
	if (old_ts == ts && old_ts!=0)
		memcpy(dt,&old_dt,sizeof(DATETIME));
	else
		old_ts = 0;
#endif

	local = LOCALTIME(ts);
	tsyear = timestamp_year(local, &rem);

	if (rem < 0)
	{
		// DPC: note that as of 3.0, the clock is initialized by default, so this error can only
		//      occur when an invalid timestamp is being converted to local time.  It should no
		//      longer occur as a result of a missing clock directive.
		//THROW("local_datetime(ts=%lli, ...): invalid timestamp cannot be converted to local time", ts);
		/*	TROUBLESHOOT
			This is the result of an internal core or module coding error which resulted in an
			invalid UTC clock time being converted to local time.
		*/
		output_error("local_datetime(ts=%lli,...): invalid local_datetime request",ts);
		return 0;
	}

	if(ts < TS_ZERO && ts > TS_MAX){ /* timestamp out of range */
		return 0;
	}
	
	if(ts == TS_NEVER){
		return 0;
	}

	/* ts is valid */
	dt->timestamp = ts;

	/* DST? */
	dt->is_dst = (tzvalid && isdst(ts));

	/* compute year */
	dt->year = tsyear;

	/* yearday and weekday */
	dt->yearday = (unsigned short)(rem / DAY);
	dt->weekday = (unsigned short)((local / DAY + DOW0 + 7) % 7);

	/* compute month */
	dt->month = 0;
	n = daysinmonth[0] * DAY;
	while(rem >= n){
		rem -= n; /* subtract n ticks from ts */
		dt->month++; /* add to month */
		if(dt->month == 12){
			dt->month = 0;
			++dt->year;
		}
		n = (daysinmonth[dt->month] + ((dt->month == 1 && ISLEAPYEAR(dt->year)) ? 1:0)) * 86400 * TS_SECOND;
		if(n < 86400 * 28){ /**/
			output_fatal("Breaking an infinite loop in local_datetime! (ts = %"FMT_INT64"ds", ts);
			/*	TROUBLESHOOT
				An internal protection against infinite loops in the time calculation
				module has encountered a critical problem.  This is often caused by
				an incorrectly initialized timezone system, a missing timezone specification before
				a timestamp was used, or a missing timezone localization in your system.
				Correct the timezone problem and try again.
			 */
			return 0;
		}
	}
	dt->month++; /* Jan=1 */

	/* compute day */
	dt->day = (unsigned short)(rem / DAY + 1);
	rem %= DAY;

	/* compute hour */
	dt->hour = (unsigned short)(rem / HOUR);
	rem %= HOUR;

	/* compute minute */
	dt->minute = (unsigned short)(rem / MINUTE);
	rem %= MINUTE;

	/* compute second */
	dt->second = (unsigned short)rem / TS_SECOND;
	rem %= SECOND;

	/* compute nanosecond */
	dt->nanosecond = (unsigned int)(rem * 1e9);

	/* determine timezone */
	strncpy(dt->tz, tzvalid ? (dt->is_dst ? tzdst : tzstd) : "GMT", sizeof(dt->tz));

	/* timezone offset in seconds */
	dt->tzoffset = tzoffset - (isdst(dt->timestamp)?3600:0);

#ifdef USE_TS_CACHE
	/* cache result */
	old_ts = ts;
	memcpy(&old_dt,dt,sizeof(old_dt));
#endif
	return 1;
}