📄 wydate.cpp
字号:
tm.tm_min=min; tm.tm_sec=sec; tm.tm_isdst=_isdst; if(tm.tm_year>=year) { WY_RETURN(Wym_ERANGE); // value conversion failed } { WyLock aa(wy_tzmutex()); TmpEnvVar rr_tz(ENVNAME_TZ); if(::setenv(ENVNAME_TZ,_tzv.c_str(),1)!=0) { WY_RETURN(Wym_ENOMEM); // man. indicates no errno and only this reason } ::tzset(); tt=std::mktime(&tm); if(tt==static_cast<std::time_t>(-1)) { WY_RETURN(Wym_ERANGE); } } _wyt.reset(tt,Wy_Nano(0)); _isdst=tm.tm_isdst; _year=year; _month=month; _mday=mday; _hour=hour; _min=min; _sec=sec; _wday=tm.tm_wday; _yday=tm.tm_yday; return(Ok);}catch(const WyStr::Reply& e) { return(e);}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};WyRet WyDate::Impl::add(const WyTimeSpec& tm)try { const WyRet r=this->set_utc(tm+_wyt); WY_RETURN(r);}catch(const WyTimeSpec::Reply& e) { return(e);};const WyDate::Impl & WyDate::Impl::operator +=(const WyTimeSpec &rhs)try { WyRet r=this->set_utc(_wyt+rhs); if(r!=Ok) { WY_THROW( WyDate::Reply(r) ); } return *this;}catch(const WyDate::Reply&) { throw;}catch(const WyTimeSpec::Reply& e) { WY_THROW( WyDate::Reply(e) );};const WyDate::Impl& WyDate::Impl::operator =(const WyDate::Impl& src) WY__TSPC(WyDate::Reply){ WyRet r=_tzv.reset(src._tzv); if(r!=Ok) { WY_THROW( WyDate::Reply(r) ); } _wyt.reset(src._wyt); _isdst=src._isdst; _year=src._year; _month=src._month; _mday=src._mday; _hour=src._hour; _min=src._min; _sec=src._sec; _wday=src._wday; _yday=src._yday; return(*this);};WyRet WyDate::Impl::_strftime(WyStr& res, const char* format) consttry { WyRet r; struct tm tm; { std::time_t tt(_wyt.second()); WyLock aa(wy_tzmutex()); TmpEnvVar rr_tz(ENVNAME_TZ); if(::setenv(ENVNAME_TZ,_tzv.c_str(),1)!=0) { WY_RETURN(Wym_ENOMEM); // man. indicates no errno and only this reason } ::tzset(); // man. indicated this can be saved, call it however. if(::localtime_r(&tt,&tm)==NULL) { WY_THROW( WyRet() ); } } WyStr buf; for(size_t bsize=256; ; bsize+=256) { if((r=buf.resize(bsize))!=Ok) { WY_RETURN(r); // only Wym_ENOMEM expected } // Note: expr uses WyStr internal buffer directly // buf.resize( ::strftime(&buf[0],bsize,format,&tm) ); // The algorithm detecting that buf space is fully used for insufficient // bsize, because ::strftime may return 0 which is valid. // if(buf.size()<bsize-1) { break; } if(bsize>=1024*128) { WY_RETURN(Wym_ENOMEM); // too big } } buf.swap(res); return(Ok);}catch(const WyStr::Reply& e) { return(e);}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};//---------------------------------------------------------------------WyDate::WyDate() WY__TSPC(WyDate::Reply)try : _dptr(new Impl()){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(const WyDate &src) WY__TSPC(WyDate::Reply)try : _dptr(new Impl(*src._dptr)){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(const char* tzval,const WyTimeSpec& ucs)try : _dptr(new Impl(tzval,ucs)){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(const WyStr& tzval,const WyTimeSpec& ucs)try : _dptr(new Impl(tzval.c_str(),ucs)){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(const char* tzval,int year,int month,int mday, int hour,int min, int sec)try : _dptr(new Impl(tzval,year,month,mday,hour,min,sec)){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(const WyStr& tzval,int year,int month,int mday, int hour,int min, int sec)try : _dptr(new Impl(tzval.c_str(),year,month,mday,hour,min,sec)){}catch(const std::bad_alloc&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );};WyDate::WyDate(WyDate& src, Wy::ByMove_t) WY__TSPC() : _dptr(src._dptr){ src._dptr=NULL;};WyDate::~WyDate() WY__TSPC(){ Wy__Base::NoCancel noc; delete _dptr; _dptr=0;};bool WyDate::is_default(void) const WY__TSPC(){ return _dptr->is_default();};void WyDate::reset(void) WY__TSPC(){ _dptr->reset();};WyRet WyDate::reset(const WyDate &rhs) WY__TSPC(){ return _dptr->reset(*rhs._dptr);};WyRet WyDate::reset(const char* tzv,const WyTimeSpec& ucs){ return _dptr->reset(tzv,ucs);};WyRet WyDate::reset(const WyStr& tzv,const WyTimeSpec& ucs){ return _dptr->reset(tzv.c_str(),ucs);};WyRet WyDate::reset(const char* tzv, int year,int month,int mday, int hour,int min, int sec){ return _dptr->reset(tzv,year,month,mday,hour,min,sec);};WyRet WyDate::reset(const WyStr& tzv, int year,int month,int mday, int hour,int min, int sec){ return _dptr->reset(tzv.c_str(),year,month,mday,hour,min,sec);};void WyDate::swap(WyDate& ano) WY__TSPC(){ // For time_zone() outputs WyStr reference, imp swap instead of // pointer swap // Wy__Base::vswap(_dptr,ano._dptr); // _dptr->swap(*ano._dptr);};// Not quit sure cstr/WyCSeg is better for this member to return?//const WyStr& WyDate::time_zone(void) const WY__TSPC(){ return _dptr->time_zone();};int WyDate::year(void) const WY__TSPC(){ return _dptr->year();};int WyDate::month(void) const WY__TSPC(){ return _dptr->month();};int WyDate::mday(void) const WY__TSPC(){ return _dptr->mday();};int WyDate::hour(void) const WY__TSPC(){ return _dptr->hour();};int WyDate::min(void) const WY__TSPC(){ return _dptr->min();};int WyDate::sec(void) const WY__TSPC(){ return _dptr->sec();};int WyDate::wday(void) const WY__TSPC(){ return _dptr->wday();};int WyDate::yday(void) const WY__TSPC(){ return _dptr->yday();};int WyDate::isdst(void) const WY__TSPC(){ return _dptr->isdst();};WyTimeSpec WyDate::utc_time(void) const WY__TSPC(){ return _dptr->utc_time();};WyRet WyDate::set_utc(const WyTimeSpec& uct){ return _dptr->set_utc(uct);};WyRet WyDate::set_date(int year,int month,int mday, int hour,int min, int sec){ return _dptr->set_date(year,month,mday,hour,min,sec);};WyRet WyDate::add(const WyTimeSpec &tm){ return _dptr->add(tm);};const WyDate& WyDate::operator =(const WyDate &rhs) WY__TSPC(Reply){ _dptr->operator =(*rhs._dptr); return(*this);};const WyDate& WyDate::operator +=(const WyTimeSpec& rhs){ _dptr->operator+=(rhs); return(*this);};bool WyDate::operator ==(const WyDate& rhs) const WY__TSPC(){ return _dptr->operator ==(*rhs._dptr);};bool WyDate::operator !=(const WyDate& rhs) const WY__TSPC(){ return _dptr->operator !=(*rhs._dptr);};//---------------------------------------------------------------------WyStr Wy::wrd(const WyDate& date)try { WyRet r; WyStr str; if((r=Wy::_mkstr(str,date.year(), 10))!=Ok) { WY_THROW(WyStr::Reply(r)); } str+='-'; { if(date.month()<10) { str+='0'; str+=char(char('0')+char(date.month()%10)); } else { str+=char(char('0')+char(date.month()/10)); str+=char(char('0')+char(date.month()%10)); } } str+='-'; { if(date.mday()<10) { str+='0'; str+=char(char('0')+char(date.mday()%10)); } else { str+=char(char('0')+char(date.mday()/10)); str+=char(char('0')+char(date.mday()%10)); } } str+=' '; { if(date.hour()<10) { str+='0'; str+=char(char('0')+char(date.hour()%10)); } else { str+=char(char('0')+char(date.hour()/10)); str+=char(char('0')+char(date.hour()%10)); } } str+=':'; { if(date.min()<10) { str+='0'; str+=char(char('0')+char(date.min()%10)); } else { str+=char(char('0')+char(date.min()/10)); str+=char(char('0')+char(date.min()%10)); } } str+='\''; { if(date.sec()<10) { str+='0'; str+=char(char('0')+char(date.sec()%10)); } else { str+=char(char('0')+char(date.sec()/10)); str+=char(char('0')+char(date.sec()%10)); } } str+= "\"("; str+= char(date.wday()+'0'); str+=')'; // add time zone information str+=' '; str+=date.time_zone(); return(str);}catch(const WyStr::Reply& e) { if(e==Wym_ENOMEM) { throw; } WY_THROW( WyRet(e) );}catch(const std::bad_alloc&) { WY_THROW(WyStr::Reply(Wym_ENOMEM));};WyRet Wy::_strftime(WyStr& res, const char* format, const WyDate& date){ return( date.wy_impl()->_strftime(res,format) );};WyDate operator +(const WyDate& dt,const WyTimeSpec& tm)try { WyDate v(dt); v+=tm; return(v);}catch(const WyDate::Reply&) { throw;} catch(const WyTimeSpec::Reply& e) { WY_THROW( WyDate::Reply(e) );};WyDate operator +(const WyTimeSpec& tm,const WyDate& dt)try { WyDate v(dt); v+=tm; return(v);}catch(const WyDate::Reply&) { throw;} catch(const WyTimeSpec::Reply& e) { WY_THROW( WyDate::Reply(e) );};#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <ctype.h>// [Internal] algorithm#1: // Get the time zone string from symbolic link LocalTimeZone // Reset res with the result//// [Ret] Ok// Wym_ESRCH Search failed for local time zone name// Wym_ENOMEM Not enough memory//static WyRet wy_local_tzname_1(WyStr& res)try { // Information from ::tzname[2] is not the expected. // 1. Few won't work and (daylight information seemd required) // 2. less readable // // It seemd ok to derive the tz data file from the time zone link file // This seemd ok for RH 9.0, not for Fedora // static const char LocalTimeZone[]="/etc/localtime"; static const char SrchPtn[]="zoneinfo/"; const size_t PBufSize=PATH_MAX+1; char* pbuf( (char*)std::malloc(PBufSize) ); if(pbuf==0) { WY_RETURN(Wym_ENOMEM); } Wy_AtDestroy<void,char*> rrid(reinterpret_cast<void(*)(char*)>(&std::free),pbuf); const int v=::readlink(LocalTimeZone,pbuf,PBufSize); if(v<0) { if(errno==ENOMEM) { WY_RETURN(Wym_ENOMEM); } WY_RETURN(Wym_ESRCH); } if(size_t(v)>=PBufSize) { WY_THROW( WyRet() ); } WyRet r; WyStr str( WyCSeg(pbuf,v) ); size_t fidx; std::free(pbuf); rrid.release(); if(str.find(&fidx,size_t(0),SrchPtn)==false) { WY_RETURN(Wym_ESRCH); } { WyStr nbuf(":"); nbuf+=str.cseg(fidx+sizeof(SrchPtn)-1); if((r=res.reset(nbuf))!=Ok) { WY_RETURN(Wym_ENOMEM); } } return(Ok);}catch(const WyStr::Reply& e) { WY_RETURN(e);};// [Internal] algorithm#2:// Get the value of environment variable TZ and reset res// with the result//// [Ret] Ok// Wym_ESRCH Search failed for local time zone name// Wym_ENOMEM Not enough memory//static WyRet wy_local_tzname_2(WyStr& res)try { bool tz_defined; WyStr tz_value; WyRet r( getenv_tz(tz_defined, tz_value) ); if(r!=Ok) { WY_RETURN(Wym_ESRCH); } if(tz_defined==false) { WY_RETURN(Wym_ESRCH); } if(tz_value.is_default()) { WY_RETURN(Wym_ESRCH); } tz_value.swap(res); return(Ok);}catch(const WyStr::Reply& e) { WY_RETURN(e);};// [Internal] algorithm#3:// From ::tzname[2]/::timezone// Reset res with the result//// [Ret] Ok// Wym_ESRCH Search failed for local time zone name// Wym_ENOMEM Not enough memory//// Note: Different source reveals different algorithms//static WyRet wy_local_tzname_3(WyStr& res)try { ::tzset(); if((::tzname[0]==0)||(*::tzname[0]==0)) { WY_RETURN(Wym_ESRCH); } if((::tzname[1]==0)||(*::tzname[1]==0)) { WY_RETURN(Wym_ESRCH); } WyStr sbuf(::daylight? ::tzname[1]: ::tzname[0]); // append sbuf with OFFSET // { long toff(::timezone); int toff_sec,toff_min; if(toff<0) { sbuf+='-'; toff=-toff; } toff_sec=toff%60; toff/=60; toff_min=toff%60; toff/=60; if(toff<10) { sbuf+=char(char('0')+char(toff)); } else { sbuf+=char(char('0')+char(toff/10)); sbuf+=char(char('0')+char(toff%10)); } if((toff_min!=0)||(toff_sec!=0)) { sbuf+=':'; if(toff_min<10) { sbuf+=char(char('0')+char(toff_min)); } else { sbuf+=char(char('0')+char(toff_min/10)); sbuf+=char(char('0')+char(toff_min%10)); } if(toff_sec!=0) { sbuf+=':'; if(toff_sec<10) { sbuf+=char(char('0')+char(toff_sec)); } else { sbuf+=char(char('0')+char(toff_sec/10)); sbuf+=char(char('0')+char(toff_sec%10)); } } } } // not right for my machine (from other document read)/* if(::daylight!=0) { if((::tzname[1]!=0)&&(*::tzname[1]!=0)) { sbuf+=::tzname[1]; } }*/ res.swap(sbuf); return(Ok);}catch(const WyStr::Reply& e) { WY_RETURN(e);};// Goal of this function is to get the identifying tzname of the system time// in effect. The return time zone string should be valid TZ value that// system time functions can recognize.//WyStr Wy::local_tzname(void)try { WyRet r; WyStr str; if((r=wy_local_tzname_1(str))==Ok) { return(str); } if((r=wy_local_tzname_3(str))==Ok) { return(str); } if((r=wy_local_tzname_2(str))==Ok) { return(str); } if(r==Wym_ESRCH) { return WyStr(WyCSeg(WyDate::TIMEZONE_UTC,sizeof(WyDate::TIMEZONE_UTC)-1)); } WY_THROW( WyDate::Reply(Wym_ENOMEM) );}catch(const WyStr::Reply&) { WY_THROW( WyDate::Reply(Wym_ENOMEM) );}catch(const WyRet& e) { WY_NDEBUG_MSG(e); WY_THROW( WyRet(e) );};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -