Blame src/TimeDate.cc

Packit 8f70b4
/*
Packit 8f70b4
 * lftp - file transfer program
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (c) 1996-2012 by Alexander V. Lukyanov (lav@yars.free.net)
Packit 8f70b4
 *
Packit 8f70b4
 * This program is free software; you can redistribute it and/or modify
Packit 8f70b4
 * it under the terms of the GNU General Public License as published by
Packit 8f70b4
 * the Free Software Foundation; either version 3 of the License, or
Packit 8f70b4
 * (at your option) any later version.
Packit 8f70b4
 *
Packit 8f70b4
 * This program is distributed in the hope that it will be useful,
Packit 8f70b4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
 * GNU General Public License for more details.
Packit 8f70b4
 *
Packit 8f70b4
 * You should have received a copy of the GNU General Public License
Packit 8f70b4
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#include <config.h>
Packit 8f70b4
#include <limits.h>
Packit 8f70b4
#include "TimeDate.h"
Packit 8f70b4
#include "misc.h"
Packit 8f70b4
#include "SMTask.h"
Packit 8f70b4
#include "strftime.h"
Packit 8f70b4
Packit 8f70b4
void time_tuple::normalize()
Packit 8f70b4
{
Packit 8f70b4
   if(usec>=1000000 || usec<=-1000000)
Packit 8f70b4
   {
Packit 8f70b4
      sec+=usec/1000000;
Packit 8f70b4
      usec%=1000000;
Packit 8f70b4
   }
Packit 8f70b4
   if(usec<0)
Packit 8f70b4
   {
Packit 8f70b4
      usec+=1000000;
Packit 8f70b4
      sec-=1;
Packit 8f70b4
   }
Packit 8f70b4
}
Packit 8f70b4
void time_tuple::addU(time_t s,int us)
Packit 8f70b4
{
Packit 8f70b4
   sec+=s;
Packit 8f70b4
   usec+=us;
Packit 8f70b4
   if(usec>=1000000)
Packit 8f70b4
      usec-=1000000,sec++;
Packit 8f70b4
   else if(usec<0)
Packit 8f70b4
      usec+=1000000,sec--;
Packit 8f70b4
}
Packit 8f70b4
void time_tuple::add(double s)
Packit 8f70b4
{
Packit 8f70b4
   time_t s_int=time_t(s);
Packit 8f70b4
   addU(s_int,int((s-s_int)*1000000));
Packit 8f70b4
}
Packit 8f70b4
double time_tuple::to_double() const
Packit 8f70b4
{
Packit 8f70b4
   return sec+usec/1000000.;
Packit 8f70b4
}
Packit 8f70b4
void Time::SetToCurrentTime()
Packit 8f70b4
{
Packit 8f70b4
   time_t s;
Packit 8f70b4
   int us;
Packit 8f70b4
   xgettimeofday(&s,&us);
Packit 8f70b4
   set(s,0,us);
Packit 8f70b4
}
Packit 8f70b4
Time::Time()
Packit 8f70b4
{
Packit 8f70b4
   // this saves a system call
Packit 8f70b4
   *this=SMTask::now;
Packit 8f70b4
}
Packit 8f70b4
bool Time::Passed(int s) const
Packit 8f70b4
{
Packit 8f70b4
   return TimeDiff(SMTask::now,*this)>=s;
Packit 8f70b4
}
Packit 8f70b4
void TimeDate::set_local_time()
Packit 8f70b4
{
Packit 8f70b4
   // avoid repeating localtime calls by caching the result.
Packit 8f70b4
   // localtime in some implementation has very bad performance,
Packit 8f70b4
   // e.g. it can re-read /etc/localtime on every call.
Packit 8f70b4
   time_t t=UnixTime();
Packit 8f70b4
   if(local_time_unix==t)
Packit 8f70b4
      return;
Packit 8f70b4
   local_time=*localtime(&t);
Packit 8f70b4
   local_time_unix=t;
Packit 8f70b4
}
Packit 8f70b4
const char *TimeDate::IsoDateTime()
Packit 8f70b4
{
Packit 8f70b4
   static char buf[21];
Packit 8f70b4
   set_local_time();
Packit 8f70b4
   strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",&local_time);
Packit 8f70b4
   buf[sizeof(buf)-1]=0;
Packit 8f70b4
   return buf;
Packit 8f70b4
}
Packit 8f70b4
int TimeDiff::MilliSeconds() const
Packit 8f70b4
{
Packit 8f70b4
   if(get_seconds()>=INT_MAX/2000)
Packit 8f70b4
      return INT_MAX/2;
Packit 8f70b4
   return get_seconds()*1000+get_milliseconds();
Packit 8f70b4
}
Packit 8f70b4
int TimeDiff::MicroSeconds() const
Packit 8f70b4
{
Packit 8f70b4
   if(get_seconds()>=INT_MAX/2000000)
Packit 8f70b4
      return INT_MAX/2;
Packit 8f70b4
   return get_seconds()*1000000+get_microseconds();
Packit 8f70b4
}
Packit 8f70b4
time_t TimeDiff::Seconds() const
Packit 8f70b4
{
Packit 8f70b4
   return get_seconds()+(get_microseconds()+500000)/1000000;
Packit 8f70b4
}
Packit 8f70b4
void TimeDiff::Set(double s)
Packit 8f70b4
{
Packit 8f70b4
   time_t s_int=(time_t)s;
Packit 8f70b4
   set(s_int,0,int((s-s_int)*1000000));
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
bool TimeInterval::Finished(const Time &base) const
Packit 8f70b4
{
Packit 8f70b4
   if(infty)
Packit 8f70b4
      return false;
Packit 8f70b4
   TimeDiff elapsed(SMTask::now,base);
Packit 8f70b4
   if(!lt(elapsed))
Packit 8f70b4
      return false;
Packit 8f70b4
   return true;
Packit 8f70b4
}
Packit 8f70b4
int TimeInterval::GetTimeoutU(const Time &base) const
Packit 8f70b4
{
Packit 8f70b4
   if(infty)
Packit 8f70b4
      return INT_MAX/2;	// to avoid dead-lock message
Packit 8f70b4
   TimeDiff elapsed(SMTask::now,base);
Packit 8f70b4
   if(lt(elapsed))
Packit 8f70b4
      return 0;
Packit 8f70b4
   elapsed-=*this;
Packit 8f70b4
   return -elapsed.MicroSeconds();
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
static void append_Nc(xstring& buf,long N,const char *c)
Packit 8f70b4
{
Packit 8f70b4
   buf.appendf("%ld%.*s",N,mblen(c,strlen(c)),c);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
const char *TimeInterval::toString(unsigned flags)
Packit 8f70b4
{
Packit 8f70b4
   if(IsInfty())
Packit 8f70b4
      return "infinity";
Packit 8f70b4
Packit 8f70b4
   long eta2=0;
Packit 8f70b4
   long ueta=0;
Packit 8f70b4
   long ueta2=0;
Packit 8f70b4
   const char *letter=0;
Packit 8f70b4
   const char *letter2=0;
Packit 8f70b4
Packit 8f70b4
   long eta=Seconds();
Packit 8f70b4
Packit 8f70b4
   xstring &buf=xstring::get_tmp("");
Packit 8f70b4
Packit 8f70b4
   // for translator: only first letter matters
Packit 8f70b4
   const char *day_c=N_("day");
Packit 8f70b4
   const char *hour_c=N_("hour");
Packit 8f70b4
   const char *minute_c=N_("minute");
Packit 8f70b4
   const char *second_c=N_("second");
Packit 8f70b4
Packit 8f70b4
   if(flags&TO_STR_TRANSLATE) {
Packit 8f70b4
      day_c=_(day_c);
Packit 8f70b4
      hour_c=_(hour_c);
Packit 8f70b4
      minute_c=_(minute_c);
Packit 8f70b4
      second_c=_(second_c);
Packit 8f70b4
   }
Packit 8f70b4
Packit 8f70b4
   if(flags&TO_STR_TERSE)
Packit 8f70b4
   {
Packit 8f70b4
      if(eta>=100*HOUR)
Packit 8f70b4
      {
Packit 8f70b4
	 ueta=(eta+DAY/2)/DAY;
Packit 8f70b4
	 eta2=eta-ueta*DAY;
Packit 8f70b4
	 letter=day_c;
Packit 8f70b4
	 if(ueta<10)
Packit 8f70b4
	 {
Packit 8f70b4
	    letter2=hour_c;
Packit 8f70b4
	    ueta2=((eta2<-HOUR/2?eta2+DAY:eta2)+HOUR/2)/HOUR;
Packit 8f70b4
	    if(ueta2>0 && eta2<-HOUR/2)
Packit 8f70b4
	       ueta--;
Packit 8f70b4
	 }
Packit 8f70b4
      }
Packit 8f70b4
      else if(eta>=100*MINUTE)
Packit 8f70b4
      {
Packit 8f70b4
	 ueta=(eta+HOUR/2)/HOUR;
Packit 8f70b4
	 eta2=eta-ueta*HOUR;
Packit 8f70b4
	 letter=hour_c;
Packit 8f70b4
	 if(ueta<10)
Packit 8f70b4
	 {
Packit 8f70b4
	    letter2=minute_c;
Packit 8f70b4
	    ueta2=((eta2<-MINUTE/2?eta2+HOUR:eta2)+MINUTE/2)/MINUTE;
Packit 8f70b4
	    if(ueta2>0 && eta2<-MINUTE/2)
Packit 8f70b4
	       ueta--;
Packit 8f70b4
	 }
Packit 8f70b4
      }
Packit 8f70b4
      else if(eta>=100)
Packit 8f70b4
      {
Packit 8f70b4
	 ueta=(eta+MINUTE/2)/MINUTE;
Packit 8f70b4
	 letter=minute_c;
Packit 8f70b4
      }
Packit 8f70b4
      else
Packit 8f70b4
      {
Packit 8f70b4
	 ueta=eta;
Packit 8f70b4
	 letter=second_c;
Packit 8f70b4
      }
Packit 8f70b4
      append_Nc(buf,ueta,letter);
Packit 8f70b4
      if(letter2 && ueta2>0)
Packit 8f70b4
	 append_Nc(buf,ueta2,letter2);
Packit 8f70b4
   }
Packit 8f70b4
   else // verbose eta (by Ben Winslow)
Packit 8f70b4
   {
Packit 8f70b4
      if(eta>=DAY)
Packit 8f70b4
	 append_Nc(buf,eta/DAY,day_c);
Packit 8f70b4
      if(eta>=HOUR)
Packit 8f70b4
	 append_Nc(buf,(eta/HOUR)%24,hour_c);
Packit 8f70b4
      if(eta>=MINUTE)
Packit 8f70b4
	 append_Nc(buf,(eta/MINUTE)%60,minute_c);
Packit 8f70b4
      append_Nc(buf,eta%60,second_c);
Packit 8f70b4
   }
Packit 8f70b4
   return buf;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
const TimeDiff& TimeDiff::valueOf(double v)
Packit 8f70b4
{
Packit 8f70b4
   static TimeDiff diff;
Packit 8f70b4
   diff.Set(v);
Packit 8f70b4
   return diff;
Packit 8f70b4
}