X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=zypp%2FDate.cc;h=4651e7220af0efc10e1e741b2f31124874e439e6;hb=HEAD;hp=45a0aad40f657d1f4e6913cdd2effe5c36c0a731;hpb=60a01b0a6bb76fadb2335cd61061ece3e0820a7f;p=platform%2Fupstream%2Flibzypp.git diff --git a/zypp/Date.cc b/zypp/Date.cc index 45a0aad..2534595 100644 --- a/zypp/Date.cc +++ b/zypp/Date.cc @@ -10,20 +10,142 @@ * */ #include -//#include "zypp/base/Logger.h" +//#include -#include "zypp/base/String.h" +#include +#include -#include "zypp/Date.h" +#include using std::endl; /////////////////////////////////////////////////////////////////// namespace zypp -{ ///////////////////////////////////////////////////////////////// +{ + /////////////////////////////////////////////////////////////////// + namespace + { + /////////////////////////////////////////////////////////////////// + /// \class LocaleGuard + /// \brief Temporarily adjust Locale + /// \ingroup RAII + struct LocaleGuard + { + LocaleGuard() + { + const char * tmp = ::setlocale( LC_TIME, NULL ); + _mylocale = tmp ? tmp : ""; + + if ( _mylocale.find( "UTF-8" ) == std::string::npos + && _mylocale.find( "utf-8" ) == std::string::npos + && _mylocale != "POSIX" + && _mylocale != "C" + && _mylocale != "" ) + { + // language[_territory][.codeset][@modifier] + // add/exchange codeset with UTF-8 + std::string needLocale = ".UTF-8"; + std::string::size_type loc = _mylocale.find_first_of( ".@" ); + if ( loc != std::string::npos ) + { + // prepend language[_territory] + needLocale = _mylocale.substr( 0, loc ) + needLocale; + loc = _mylocale.find_last_of( "@" ); + if ( loc != std::string::npos ) + { + // append [@modifier] + needLocale += _mylocale.substr( loc ); + } + } + else + { + // append ".UTF-8" + needLocale = _mylocale + needLocale; + } + ::setlocale( LC_TIME, needLocale.c_str() ); + } + else + { + // no need to change the locale + _mylocale.clear(); + } + } + + ~LocaleGuard() + { + if ( ! _mylocale.empty() ) + ::setlocale( LC_TIME, _mylocale.c_str() ); + } + private: + std::string _mylocale; + }; + /////////////////////////////////////////////////////////////////// - static std::string adjustLocale(); - static void restoreLocale(const std::string & locale); + inline bool isDST( struct tm & tm ) + { + time_t t = ::mktime( &tm ); + struct tm *tm2 = ::localtime( &t ); + return ( tm2 && tm2->tm_isdst > 0 ); + } + + inline const char * _dateFormat( Date::DateFormat dateFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + "%Y-%m-%d", ///< 2014-02-07 + "%Y-%m", ///< 2014-02 + "%Y", ///< 2014 + "%G-W%V", ///< 2014-W06 + "%G-W%V-%u", ///< 2014-W06-5 (1 is Monday) + "%Y-%j", ///< 2014-038 + }; + return fmt[dateFormat_r.asIntegral()]; + } + + inline const char * _timeFormat( Date::TimeFormat timeFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + "%H:%M:%S", ///< 07:06:41 + "%H:%M", ///< 07:06 + "%H", ///< 07 + }; + return fmt[timeFormat_r.asIntegral()]; + } + + inline const char * _timeZoneFormat( Date::TimeZoneFormat timeZoneFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + " %Z", ///< UTC, CET, ... + "%z", ///< +0000 + }; + return fmt[timeZoneFormat_r.asIntegral()]; + } + + inline std::string doForm( const std::string & format_r, Date::TimeBase base_r, const Date::ValueType & date_r ) + { + if ( ! date_r ) + return "0"; + + LocaleGuard guard; + static char buf[512]; + if ( ! strftime( buf, 512, format_r.c_str(), (base_r == Date::TB_UTC ? gmtime : localtime)( &date_r ) ) ) + *buf = '\0'; + else + { + // strip a trailing '00' in a timeZoneFormat + unsigned l = ::strlen( buf ); + if ( l >= 5 + && ( buf[l-1] == '0' ) + && ( buf[l-2] == '0' ) + && ( buf[l-5] == '+' || buf[l-5] == '-') ) + buf[l-2] = '\0'; + } + return buf; + } + } // namespace + /////////////////////////////////////////////////////////////////// const Date::ValueType Date::second; const Date::ValueType Date::minute; @@ -38,97 +160,83 @@ namespace zypp const Date::ValueType Date::year366; const Date::ValueType Date::year; - /////////////////////////////////////////////////////////////////// - // - // METHOD NAME : Date::Date - // METHOD TYPE : Constructor - // Date::Date( const std::string & seconds_r ) { str::strtonum( seconds_r, _date ); } Date::Date( const std::string & date_str, const std::string & format ) + : _date( Date( date_str, format, TB_LOCALTIME ) ) + {} + + Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r ) : _date(0) { - struct tm tm = {0}; - std::string thisLocale = adjustLocale(); + LocaleGuard guard; + struct tm tm = {0,0,0,0,0,0,0,0,0,0,0}; char * res = ::strptime( date_str.c_str(), format.c_str(), &tm ); - if ( res != NULL ) - _date = ::timelocal( &tm ); - - restoreLocale(thisLocale); - if (res == NULL) - throw DateFormatException( - str::form( "Invalid date format: '%s'", date_str.c_str() ) ); - } - - /////////////////////////////////////////////////////////////////// - // - // METHOD NAME : Date::form - // METHOD TYPE : std::string - // - std::string Date::form( const std::string & format_r ) const - { - static char buf[1024]; - std::string thisLocale = adjustLocale(); + throw DateFormatException( str::form( "Invalid date format: '%s'", date_str.c_str() ) ); - if ( ! strftime( buf, 1024, format_r.c_str(), localtime( &_date ) ) ) - *buf = '\0'; + if ( isDST(tm) ) + tm.tm_isdst = 1; + _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm ); + } - restoreLocale(thisLocale); + std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const + { return doForm( format_r, base_r, _date ); } - return buf; + std::string Date::print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const + { + str::Str str; + if ( dateFormat_r != DateFormat::none ) + str << _dateFormat( dateFormat_r ); + if ( timeFormat_r != TimeFormat::none ) + { + if ( dateFormat_r != DateFormat::none ) + str << ' '; + str << _timeFormat( timeFormat_r ); + if ( timeZoneFormat_r != TimeZoneFormat::none ) + str << _timeZoneFormat( timeZoneFormat_r ); + } + return doForm( str, base_r, _date ); } - static std::string adjustLocale() + std::string Date::printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const { - const char * tmp = ::setlocale( LC_TIME, NULL ); - std::string thisLocale( tmp ? tmp : "" ); - - if ( thisLocale.find( "UTF-8" ) == std::string::npos - && thisLocale.find( "utf-8" ) == std::string::npos - && thisLocale != "POSIX" - && thisLocale != "C" - && thisLocale != "" ) + str::Str str; + if ( dateFormat_r != DateFormat::none ) + str << _dateFormat( dateFormat_r ); + if ( timeFormat_r != TimeFormat::none ) { - // language[_territory][.codeset][@modifier] - // add/exchange codeset with UTF-8 - std::string needLocale = ".UTF-8"; - std::string::size_type loc = thisLocale.find_first_of( ".@" ); - if ( loc != std::string::npos ) + if ( dateFormat_r != DateFormat::none ) + str << 'T'; + str << _timeFormat( timeFormat_r ); + switch ( timeZoneFormat_r.asEnum() ) { - // prepend language[_territory] - needLocale = thisLocale.substr( 0, loc ) + needLocale; - loc = thisLocale.find_last_of( "@" ); - if ( loc != std::string::npos ) - { - // append [@modifier] - needLocale += thisLocale.substr( loc ); - } + case TimeZoneFormat::none: + break; + case TimeZoneFormat::name: + if ( base_r == TB_UTC ) + { + str << 'Z'; + break; + } + // else: FALLTHROUGH and print offset! + case TimeZoneFormat::offset: + str << _timeZoneFormat( TimeZoneFormat::offset ); + break; } - else - { - // append ".UTF-8" - needLocale = thisLocale + needLocale; - } - ::setlocale( LC_TIME, needLocale.c_str() ); } - else - { - // no need to change the locale - thisLocale.clear(); - } - - return thisLocale; + return doForm( str, base_r, _date ); } - static void restoreLocale(const std::string & locale) + std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r ) { - if ( ! locale.empty() ) - ::setlocale( LC_TIME, locale.c_str() ); + return xmlout::node( str, name_r, { + { "time_t", Date::ValueType(obj) }, + { "text", obj.printISO( Date::TB_UTC ) }, + } ); } - ///////////////////////////////////////////////////////////////// } // namespace zypp ///////////////////////////////////////////////////////////////////