libzypp  17.37.5
Date.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 //#include <zypp-core/base/Logger.h>
14 
15 #include <zypp-core/base/String.h>
16 #include <zypp-core/base/Xml.h>
17 
18 #include <zypp-core/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(const LocaleGuard &) = delete;
75  LocaleGuard(LocaleGuard &&) = delete;
76  LocaleGuard &operator=(const LocaleGuard &) = delete;
77  LocaleGuard &operator=(LocaleGuard &&) = delete;
78 
79  ~LocaleGuard() {
80  if ( ! _mylocale.empty() )
81  ::setlocale( LC_TIME, _mylocale.c_str() );
82  }
83 
84  private:
85  std::string _mylocale;
86  };
88 
89  inline bool isDST( struct tm & tm )
90  {
91  time_t t = ::mktime( &tm );
92  struct tm *tm2 = ::localtime( &t );
93  return ( tm2 && tm2->tm_isdst > 0 );
94  }
95 
96  inline const char * _dateFormat( Date::DateFormat dateFormat_r )
97  {
98  static const char * fmt[] = {
99  "",
100  "%Y-%m-%d",
101  "%Y-%m",
102  "%Y",
103  "%G-W%V",
104  "%G-W%V-%u",
105  "%Y-%j",
106  };
107  return fmt[dateFormat_r.asIntegral()];
108  }
109 
110  inline const char * _timeFormat( Date::TimeFormat timeFormat_r )
111  {
112  static const char * fmt[] = {
113  "",
114  "%H:%M:%S",
115  "%H:%M",
116  "%H",
117  };
118  return fmt[timeFormat_r.asIntegral()];
119  }
120 
121  inline const char * _timeZoneFormat( Date::TimeZoneFormat timeZoneFormat_r )
122  {
123  static const char * fmt[] = {
124  "",
125  " %Z",
126  "%z",
127  };
128  return fmt[timeZoneFormat_r.asIntegral()];
129  }
130 
131  inline std::string doForm( const std::string & format_r, Date::TimeBase base_r, const Date::ValueType & date_r )
132  {
133  if ( ! date_r )
134  return "0";
135 
136  LocaleGuard guard;
137  static char buf[512];
138  if ( ! strftime( buf, 512, format_r.c_str(), (base_r == Date::TB_UTC ? gmtime : localtime)( &date_r ) ) )
139  *buf = '\0';
140  else
141  {
142  // strip a trailing '00' in a timeZoneFormat
143  unsigned l = ::strlen( buf );
144  if ( l >= 5
145  && ( buf[l-1] == '0' )
146  && ( buf[l-2] == '0' )
147  && ( buf[l-5] == '+' || buf[l-5] == '-') )
148  buf[l-2] = '\0';
149  }
150  return buf;
151  }
152  } // namespace
154 
167 
168  Date::Date( const std::string & seconds_r )
169  { str::strtonum( seconds_r, _date ); }
170 
171  Date::Date( const std::string & date_str, const std::string & format )
172  : _date( Date( date_str, format, TB_LOCALTIME ) )
173  {}
174 
175  Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r )
176  : _date(0)
177  {
178  LocaleGuard guard;
179 
180  struct tm tm = {0,0,0,0,0,0,0,0,0,0,0};
181  char * res = ::strptime( date_str.c_str(), format.c_str(), &tm );
182  if (res == NULL)
183  throw DateFormatException( str::form( "Invalid date format: '%s'", date_str.c_str() ) );
184 
185  if ( isDST(tm) )
186  tm.tm_isdst = 1;
187  _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm );
188  }
189 
190  std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const
191  { return doForm( format_r, base_r, _date ); }
192 
193  std::string Date::print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
194  {
195  str::Str str;
196  if ( dateFormat_r != DateFormat::none )
197  str << _dateFormat( dateFormat_r );
198  if ( timeFormat_r != TimeFormat::none )
199  {
200  if ( dateFormat_r != DateFormat::none )
201  str << ' ';
202  str << _timeFormat( timeFormat_r );
203  if ( timeZoneFormat_r != TimeZoneFormat::none )
204  str << _timeZoneFormat( timeZoneFormat_r );
205  }
206  return doForm( str, base_r, _date );
207  }
208 
209  std::string Date::printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const
210  {
211  str::Str str;
212  if ( dateFormat_r != DateFormat::none )
213  str << _dateFormat( dateFormat_r );
214  if ( timeFormat_r != TimeFormat::none )
215  {
216  if ( dateFormat_r != DateFormat::none )
217  str << 'T';
218  str << _timeFormat( timeFormat_r );
219  switch ( timeZoneFormat_r.asEnum() )
220  {
222  break;
223  case TimeZoneFormat::name:
224  if ( base_r == TB_UTC )
225  {
226  str << 'Z';
227  break;
228  }
229  // else: FALLTHROUGH and print offset!
230  case TimeZoneFormat::offset:
231  str << _timeZoneFormat( TimeZoneFormat::offset );
232  break;
233  }
234  }
235  return doForm( str, base_r, _date );
236  }
237 
238  std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r )
239  {
240  return xmlout::node( str, name_r, {
241  { "time_t", Date::ValueType(obj) },
242  { "text", obj.printISO( Date::TB_UTC ) },
243  } );
244  }
245 
246 } // namespace zypp
static const ValueType day
Definition: Date.h:44
std::ostream & node(std::ostream &out_r, const std::string &name_r, Node::Attr attr_r)
Definition: Xml.h:204
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 &#39;2014-02-07 07:06:41 CET&#39; The default is DateFormat::calendar, TimeFormat::seconds...
Definition: Date.cc:193
static const ValueType minute
Definition: Date.h:42
static const ValueType month31
Definition: Date.h:48
LocaleGuard(int category_r, const std::string &value_r="C")
Ctor saving the current locale category value.
Definition: LocaleGuard.h:34
String related utilities and Regular expression matching.
base::EnumClass< ETimeZoneFormatDef > TimeZoneFormat
&#39;enum class TimeZoneFormat&#39;
Definition: Date.h:159
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:39
~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:85
static const ValueType month
Definition: Date.h:49
static const ValueType month29
Definition: Date.h:46
time_t ValueType
Definition: Date.h:38
ValueType _date
Calendar time.
Definition: Date.h:247
Store and operate on date (time_t).
Definition: Date.h:32
std::ostream & dumpAsXmlOn(std::ostream &str, const Repository &obj)
Definition: Repository.cc:407
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition: Date.h:112
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212
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:459
base::EnumClass< EDateFormatDef > DateFormat
&#39;enum class DateFormat&#39;
Definition: Date.h:142
static const ValueType hour
Definition: Date.h:43
base::EnumClass< ETimeFormatDef > TimeFormat
&#39;enum class TimeFormat&#39;
Definition: Date.h:151
static const ValueType year366
Definition: Date.h:51
TimeBase
Definition: Date.h:54
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
SolvableIdType size_type
Definition: PoolMember.h:126
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 &#39;2014-02-07T07:06:41+01&#39;
Definition: Date.cc:209
static const ValueType second
Definition: Date.h:41