1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
13 //#include "zypp/base/Logger.h"
15 #include "zypp/base/String.h"
16 #include "zypp/base/Xml.h"
18 #include "zypp/Date.h"
22 ///////////////////////////////////////////////////////////////////
25 ///////////////////////////////////////////////////////////////////
28 ///////////////////////////////////////////////////////////////////
29 /// \class LocaleGuard
30 /// \brief Temporarily adjust Locale
36 const char * tmp = ::setlocale( LC_TIME, NULL );
37 _mylocale = tmp ? tmp : "";
39 if ( _mylocale.find( "UTF-8" ) == std::string::npos
40 && _mylocale.find( "utf-8" ) == std::string::npos
41 && _mylocale != "POSIX"
45 // language[_territory][.codeset][@modifier]
46 // add/exchange codeset with UTF-8
47 std::string needLocale = ".UTF-8";
48 std::string::size_type loc = _mylocale.find_first_of( ".@" );
49 if ( loc != std::string::npos )
51 // prepend language[_territory]
52 needLocale = _mylocale.substr( 0, loc ) + needLocale;
53 loc = _mylocale.find_last_of( "@" );
54 if ( loc != std::string::npos )
57 needLocale += _mylocale.substr( loc );
63 needLocale = _mylocale + needLocale;
65 ::setlocale( LC_TIME, needLocale.c_str() );
69 // no need to change the locale
76 if ( ! _mylocale.empty() )
77 ::setlocale( LC_TIME, _mylocale.c_str() );
80 std::string _mylocale;
82 ///////////////////////////////////////////////////////////////////
84 inline bool isDST( struct tm & tm )
86 time_t t = ::mktime( &tm );
87 struct tm *tm2 = ::localtime( &t );
88 return ( tm2 && tm2->tm_isdst > 0 );
91 inline const char * _dateFormat( Date::DateFormat dateFormat_r )
93 static const char * fmt[] = {
95 "%Y-%m-%d", ///< 2014-02-07
98 "%G-W%V", ///< 2014-W06
99 "%G-W%V-%u", ///< 2014-W06-5 (1 is Monday)
100 "%Y-%j", ///< 2014-038
102 return fmt[static_cast<std::underlying_type<Date::DateFormat::Enum>::type>(dateFormat_r.inSwitch())];
105 inline const char * _timeFormat( Date::TimeFormat timeFormat_r )
107 static const char * fmt[] = {
109 "%H:%M:%S", ///< 07:06:41
113 return fmt[static_cast<std::underlying_type<Date::TimeFormat::Enum>::type>(timeFormat_r.inSwitch())];
116 inline const char * _timeZoneFormat( Date::TimeZoneFormat timeZoneFormat_r )
118 static const char * fmt[] = {
120 " %Z", ///< UTC, CET, ...
123 return fmt[static_cast<std::underlying_type<Date::TimeZoneFormat::Enum>::type>(timeZoneFormat_r.inSwitch())];
126 inline std::string doForm( const std::string & format_r, Date::TimeBase base_r, const Date::ValueType & date_r )
132 static char buf[512];
133 if ( ! strftime( buf, 512, format_r.c_str(), (base_r == Date::TB_UTC ? gmtime : localtime)( &date_r ) ) )
137 // strip a trailing '00' in a timeZoneFormat
138 unsigned l = ::strlen( buf );
140 && ( buf[l-1] == '0' )
141 && ( buf[l-2] == '0' )
142 && ( buf[l-5] == '+' || buf[l-5] == '-') )
148 ///////////////////////////////////////////////////////////////////
150 const Date::ValueType Date::second;
151 const Date::ValueType Date::minute;
152 const Date::ValueType Date::hour;
153 const Date::ValueType Date::day;
154 const Date::ValueType Date::month28;
155 const Date::ValueType Date::month29;
156 const Date::ValueType Date::month30;
157 const Date::ValueType Date::month31;
158 const Date::ValueType Date::month;
159 const Date::ValueType Date::year365;
160 const Date::ValueType Date::year366;
161 const Date::ValueType Date::year;
163 Date::Date( const std::string & seconds_r )
164 { str::strtonum( seconds_r, _date ); }
166 Date::Date( const std::string & date_str, const std::string & format )
167 : _date( Date( date_str, format, TB_LOCALTIME ) )
170 Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r )
175 struct tm tm = {0,0,0,0,0,0,0,0,0,0,0};
176 char * res = ::strptime( date_str.c_str(), format.c_str(), &tm );
178 throw DateFormatException( str::form( "Invalid date format: '%s'", date_str.c_str() ) );
182 _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm );
185 std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const
186 { return doForm( format_r, base_r, _date ); }
188 std::string Date::print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
191 if ( dateFormat_r != DateFormat::none )
192 str << _dateFormat( dateFormat_r );
193 if ( timeFormat_r != TimeFormat::none )
195 if ( dateFormat_r != DateFormat::none )
197 str << _timeFormat( timeFormat_r );
198 if ( timeZoneFormat_r != TimeZoneFormat::none )
199 str << _timeZoneFormat( timeZoneFormat_r );
201 return doForm( str, base_r, _date );
204 std::string Date::printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
207 if ( dateFormat_r != DateFormat::none )
208 str << _dateFormat( dateFormat_r );
209 if ( timeFormat_r != TimeFormat::none )
211 if ( dateFormat_r != DateFormat::none )
213 str << _timeFormat( timeFormat_r );
214 switch ( timeZoneFormat_r.inSwitch() )
216 case TimeZoneFormat::none:
218 case TimeZoneFormat::name:
219 if ( base_r == TB_UTC )
224 // else: FALLTHROUGH and print offset!
225 case TimeZoneFormat::offset:
226 str << _timeZoneFormat( TimeZoneFormat::offset );
230 return doForm( str, base_r, _date );
233 std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r )
235 return xmlout::node( str, name_r, {
236 { "time_t", Date::ValueType(obj) },
237 { "text", obj.printISO() },
242 ///////////////////////////////////////////////////////////////////