|
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 |
}
|