libzypp  10.5.0
Date.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 //#include "zypp/base/Logger.h"
00014 
00015 #include "zypp/base/String.h"
00016 
00017 #include "zypp/Date.h"
00018 
00019 using std::endl;
00020 
00022 namespace zypp
00023 { 
00024 
00025   static std::string adjustLocale();
00026   static void restoreLocale(const std::string & locale);
00027 
00028   namespace
00029   {
00030     inline bool isDST( struct tm & tm )
00031     {
00032       time_t t = ::mktime( &tm );
00033       struct tm *tm2 = ::localtime( &t );
00034       return ( tm2 && tm2->tm_isdst > 0 );
00035     }
00036   }
00037 
00038   const Date::ValueType Date::second;
00039   const Date::ValueType Date::minute;
00040   const Date::ValueType Date::hour;
00041   const Date::ValueType Date::day;
00042   const Date::ValueType Date::month28;
00043   const Date::ValueType Date::month29;
00044   const Date::ValueType Date::month30;
00045   const Date::ValueType Date::month31;
00046   const Date::ValueType Date::month;
00047   const Date::ValueType Date::year365;
00048   const Date::ValueType Date::year366;
00049   const Date::ValueType Date::year;
00050 
00052   //
00053   //    METHOD NAME : Date::Date
00054   //    METHOD TYPE : Constructor
00055   //
00056   Date::Date( const std::string & seconds_r )
00057   { str::strtonum( seconds_r, _date ); }
00058 
00059   Date::Date( const std::string & date_str, const std::string & format )
00060     : _date( Date( date_str, format, TB_LOCALTIME ) )
00061   {}
00062 
00063   Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r )
00064     : _date(0)
00065   {
00066     struct tm tm = {0,0,0,0,0,0,0,0,0,0,0};
00067     std::string thisLocale = adjustLocale();
00068 
00069     char * res = ::strptime( date_str.c_str(), format.c_str(), &tm );
00070     if ( isDST(tm) )
00071       tm.tm_isdst = 1;
00072     if ( res != NULL )
00073       _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm );
00074 
00075     restoreLocale(thisLocale);
00076 
00077     if (res == NULL)
00078       throw DateFormatException(
00079           str::form( "Invalid date format: '%s'", date_str.c_str() ) );
00080   }
00081 
00082 
00084   //
00085   //    METHOD NAME : Date::form
00086   //    METHOD TYPE : std::string
00087   //
00088   std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const
00089   {
00090     static char buf[1024];
00091     std::string thisLocale = adjustLocale();
00092 
00093     if ( ! strftime( buf, 1024, format_r.c_str(), (base_r == TB_UTC ? gmtime : localtime)( &_date ) ) )
00094       *buf = '\0';
00095 
00096     restoreLocale(thisLocale);
00097 
00098     return buf;
00099   }
00100 
00101   static std::string adjustLocale()
00102   {
00103     const char * tmp = ::setlocale( LC_TIME, NULL );
00104     std::string thisLocale( tmp ? tmp : "" );
00105 
00106     if (    thisLocale.find( "UTF-8" ) == std::string::npos
00107          && thisLocale.find( "utf-8" ) == std::string::npos
00108          && thisLocale != "POSIX"
00109          && thisLocale != "C"
00110          && thisLocale != "" )
00111     {
00112       // language[_territory][.codeset][@modifier]
00113       // add/exchange codeset with UTF-8
00114       std::string needLocale = ".UTF-8";
00115       std::string::size_type loc = thisLocale.find_first_of( ".@" );
00116       if ( loc != std::string::npos )
00117       {
00118         // prepend language[_territory]
00119         needLocale = thisLocale.substr( 0, loc ) + needLocale;
00120         loc = thisLocale.find_last_of( "@" );
00121         if ( loc != std::string::npos )
00122         {
00123           // append [@modifier]
00124           needLocale += thisLocale.substr( loc );
00125         }
00126       }
00127       else
00128       {
00129         // append ".UTF-8"
00130         needLocale = thisLocale + needLocale;
00131       }
00132       ::setlocale( LC_TIME, needLocale.c_str() );
00133     }
00134     else
00135     {
00136       // no need to change the locale
00137       thisLocale.clear();
00138     }
00139 
00140     return thisLocale;
00141   }
00142 
00143   static void restoreLocale(const std::string & locale)
00144   {
00145     if ( ! locale.empty() )
00146       ::setlocale( LC_TIME, locale.c_str() );
00147   }
00148 
00150 } // namespace zypp