libzypp  15.28.6
Date.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 //#include "zypp/base/Logger.h"
14 
15 #include "zypp/base/String.h"
16 #include "zypp/base/Xml.h"
17 
18 #include "zypp/Date.h"
19 
20 using std::endl;
21 
23 namespace zypp
24 {
26  namespace
27  {
32  struct LocaleGuard
33  {
34  LocaleGuard()
35  {
36  const char * tmp = ::setlocale( LC_TIME, NULL );
37  _mylocale = tmp ? tmp : "";
38 
39  if ( _mylocale.find( "UTF-8" ) == std::string::npos
40  && _mylocale.find( "utf-8" ) == std::string::npos
41  && _mylocale != "POSIX"
42  && _mylocale != "C"
43  && _mylocale != "" )
44  {
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 )
50  {
51  // prepend language[_territory]
52  needLocale = _mylocale.substr( 0, loc ) + needLocale;
53  loc = _mylocale.find_last_of( "@" );
54  if ( loc != std::string::npos )
55  {
56  // append [@modifier]
57  needLocale += _mylocale.substr( loc );
58  }
59  }
60  else
61  {
62  // append ".UTF-8"
63  needLocale = _mylocale + needLocale;
64  }
65  ::setlocale( LC_TIME, needLocale.c_str() );
66  }
67  else
68  {
69  // no need to change the locale
70  _mylocale.clear();
71  }
72  }
73 
74  ~LocaleGuard()
75  {
76  if ( ! _mylocale.empty() )
77  ::setlocale( LC_TIME, _mylocale.c_str() );
78  }
79  private:
80  std::string _mylocale;
81  };
83 
84  inline bool isDST( struct tm & tm )
85  {
86  time_t t = ::mktime( &tm );
87  struct tm *tm2 = ::localtime( &t );
88  return ( tm2 && tm2->tm_isdst > 0 );
89  }
90 
91  inline const char * _dateFormat( Date::DateFormat dateFormat_r )
92  {
93  static const char * fmt[] = {
94  "",
95  "%Y-%m-%d",
96  "%Y-%m",
97  "%Y",
98  "%G-W%V",
99  "%G-W%V-%u",
100  "%Y-%j",
101  };
102  return fmt[dateFormat_r.asIntegral()];
103  }
104 
105  inline const char * _timeFormat( Date::TimeFormat timeFormat_r )
106  {
107  static const char * fmt[] = {
108  "",
109  "%H:%M:%S",
110  "%H:%M",
111  "%H",
112  };
113  return fmt[timeFormat_r.asIntegral()];
114  }
115 
116  inline const char * _timeZoneFormat( Date::TimeZoneFormat timeZoneFormat_r )
117  {
118  static const char * fmt[] = {
119  "",
120  " %Z",
121  "%z",
122  };
123  return fmt[timeZoneFormat_r.asIntegral()];
124  }
125 
126  inline std::string doForm( const std::string & format_r, Date::TimeBase base_r, const Date::ValueType & date_r )
127  {
128  if ( ! date_r )
129  return "0";
130 
131  LocaleGuard guard;
132  static char buf[512];
133  if ( ! strftime( buf, 512, format_r.c_str(), (base_r == Date::TB_UTC ? gmtime : localtime)( &date_r ) ) )
134  *buf = '\0';
135  else
136  {
137  // strip a trailing '00' in a timeZoneFormat
138  unsigned l = ::strlen( buf );
139  if ( l >= 5
140  && ( buf[l-1] == '0' )
141  && ( buf[l-2] == '0' )
142  && ( buf[l-5] == '+' || buf[l-5] == '-') )
143  buf[l-2] = '\0';
144  }
145  return buf;
146  }
147  } // namespace
149 
162 
163  Date::Date( const std::string & seconds_r )
164  { str::strtonum( seconds_r, _date ); }
165 
166  Date::Date( const std::string & date_str, const std::string & format )
167  : _date( Date( date_str, format, TB_LOCALTIME ) )
168  {}
169 
170  Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r )
171  : _date(0)
172  {
173  LocaleGuard guard;
174 
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 );
177  if (res == NULL)
178  throw DateFormatException( str::form( "Invalid date format: '%s'", date_str.c_str() ) );
179 
180  if ( isDST(tm) )
181  tm.tm_isdst = 1;
182  _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm );
183  }
184 
185  std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const
186  { return doForm( format_r, base_r, _date ); }
187 
188  std::string Date::print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
189  {
190  str::Str str;
191  if ( dateFormat_r != DateFormat::none )
192  str << _dateFormat( dateFormat_r );
193  if ( timeFormat_r != TimeFormat::none )
194  {
195  if ( dateFormat_r != DateFormat::none )
196  str << ' ';
197  str << _timeFormat( timeFormat_r );
198  if ( timeZoneFormat_r != TimeZoneFormat::none )
199  str << _timeZoneFormat( timeZoneFormat_r );
200  }
201  return doForm( str, base_r, _date );
202  }
203 
204  std::string Date::printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
205  {
206  str::Str str;
207  if ( dateFormat_r != DateFormat::none )
208  str << _dateFormat( dateFormat_r );
209  if ( timeFormat_r != TimeFormat::none )
210  {
211  if ( dateFormat_r != DateFormat::none )
212  str << 'T';
213  str << _timeFormat( timeFormat_r );
214  switch ( timeZoneFormat_r.asEnum() )
215  {
216  case TimeZoneFormat::none:
217  break;
218  case TimeZoneFormat::name:
219  if ( base_r == TB_UTC )
220  {
221  str << 'Z';
222  break;
223  }
224  // else: FALLTHROUGH and print offset!
225  case TimeZoneFormat::offset:
226  str << _timeZoneFormat( TimeZoneFormat::offset );
227  break;
228  }
229  }
230  return doForm( str, base_r, _date );
231  }
232 
233  std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r )
234  {
235  return xmlout::node( str, name_r, {
236  { "time_t", Date::ValueType(obj) },
237  { "text", obj.printISO() },
238  } );
239  }
240 
241 } // namespace zypp
static const ValueType day
Definition: Date.h:44
base::EnumClass< EDateFormatDef > DateFormat
'enum class DateFormat'
Definition: Date.h:142
std::ostream & node(std::ostream &out_r, const std::string &name_r, Node::Attr attr_r)
Definition: Xml.h:175
static const ValueType minute
Definition: Date.h:42
static const ValueType month31
Definition: Date.h:48
std::string printISO(DateFormat dateFormat_r=DateFormat::calendar, TimeFormat timeFormat_r=TimeFormat::seconds, TimeZoneFormat timeZoneFormat_r=TimeZoneFormat::name, TimeBase base_r=TB_LOCALTIME) const
Default ISO 8601 format is '2014-02-07T07:06:41+01'
Definition: Date.cc:204
LocaleGuard(int category_r, const std::string &value_r="C")
Ctor saving the current locale category value.
Definition: LocaleGuard.h:34
Date()
Default ctor: 0.
Definition: Date.h:57
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:36
~LocaleGuard()
Dtor asserts the saved locale category value is restored.
Definition: LocaleGuard.h:47
static const ValueType month30
Definition: Date.h:47
std::string _mylocale
Definition: Date.cc:80
static const ValueType month
Definition: Date.h:49
static const ValueType month29
Definition: Date.h:46
ValueType _date
Calendar time.
Definition: Date.h:247
Store and operate on date (time_t).
Definition: Date.h:32
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:210
Temorarily change a locale category value.
Definition: LocaleGuard.h:27
static const ValueType year365
Definition: Date.h:50
static const ValueType month28
Definition: Date.h:45
static const ValueType year
Definition: Date.h:52
TInt strtonum(const C_Str &str)
Parsing numbers from string.
Definition: String.h:403
SolvableIdType size_type
Definition: PoolMember.h:152
base::EnumClass< ETimeZoneFormatDef > TimeZoneFormat
'enum class TimeZoneFormat'
Definition: Date.h:159
static const ValueType hour
Definition: Date.h:43
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition: Date.h:112
time_t ValueType
Definition: Date.h:38
base::EnumClass< ETimeFormatDef > TimeFormat
'enum class TimeFormat'
Definition: Date.h:151
static const ValueType year366
Definition: Date.h:51
std::string print(DateFormat dateFormat_r=DateFormat::calendar, TimeFormat timeFormat_r=TimeFormat::seconds, TimeZoneFormat timeZoneFormat_r=TimeZoneFormat::name, TimeBase base_r=TB_LOCALTIME) const
Default format is '2014-02-07 07:06:41 CET' The default is DateFormat::calendar, TimeFormat::seconds...
Definition: Date.cc:188
TimeBase
Definition: Date.h:54
static const ValueType second
Definition: Date.h:41
std::ostream & dumpAsXmlOn(std::ostream &str, const Tp &obj, const std::string &name_r)
Definition: Xml.h:185