libzypp: zypp-core/Date.cc Source File

libzypp 17.38.9

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
20using std::endl;
21
23namespace 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
155 const Date::ValueType Date::second;
156 const Date::ValueType Date::minute;
157 const Date::ValueType Date::hour;
158 const Date::ValueType Date::day;
159 const Date::ValueType Date::month28;
160 const Date::ValueType Date::month29;
161 const Date::ValueType Date::month30;
162 const Date::ValueType Date::month31;
163 const Date::ValueType Date::month;
164 const Date::ValueType Date::year365;
165 const Date::ValueType Date::year366;
166 const Date::ValueType Date::year;
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 {
221 case TimeZoneFormat::none:
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
Date.h
String.h
Xml.h
zypp::DateFormatException
Definition Date.h:262
zypp::Date
Store and operate on date (time_t).
Definition Date.h:33
zypp::Date::_date
ValueType _date
Calendar time.
Definition Date.h:247
zypp::Date::print
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:193
zypp::Date::year365
static const ValueType year365
Definition Date.h:50
zypp::Date::printISO
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:209
zypp::Date::Date
Date()
Default ctor: 0.
Definition Date.h:57
zypp::Date::TimeBase
TimeBase
Definition Date.h:54
zypp::Date::TB_LOCALTIME
@ TB_LOCALTIME
Definition Date.h:54
zypp::Date::TB_UTC
@ TB_UTC
Definition Date.h:54
zypp::Date::hour
static const ValueType hour
Definition Date.h:43
zypp::Date::day
static const ValueType day
Definition Date.h:44
zypp::Date::month31
static const ValueType month31
Definition Date.h:48
zypp::Date::minute
static const ValueType minute
Definition Date.h:42
zypp::Date::DateFormat
base::EnumClass< EDateFormatDef > DateFormat
'enum class DateFormat'
Definition Date.h:142
zypp::Date::month30
static const ValueType month30
Definition Date.h:47
zypp::Date::month
static const ValueType month
Definition Date.h:49
zypp::Date::year366
static const ValueType year366
Definition Date.h:51
zypp::Date::TimeZoneFormat
base::EnumClass< ETimeZoneFormatDef > TimeZoneFormat
'enum class TimeZoneFormat'
Definition Date.h:159
zypp::Date::ValueType
time_t ValueType
Definition Date.h:38
zypp::Date::form
std::string form(const std::string &format_r) const
Return string representation according to format as localtime.
Definition Date.h:112
zypp::Date::month28
static const ValueType month28
Definition Date.h:45
zypp::Date::TimeFormat
base::EnumClass< ETimeFormatDef > TimeFormat
'enum class TimeFormat'
Definition Date.h:151
zypp::Date::month29
static const ValueType month29
Definition Date.h:46
zypp::Date::second
static const ValueType second
Definition Date.h:41
zypp::Date::year
static const ValueType year
Definition Date.h:52
zypp::LocaleGuard
Temorarily change a locale category value.
Definition LocaleGuard.h:28
zypp::LocaleGuard::LocaleGuard
LocaleGuard(int category_r, const std::string &value_r="C")
Ctor saving the current locale category value.
Definition LocaleGuard.h:34
zypp::LocaleGuard::~LocaleGuard
~LocaleGuard()
Dtor asserts the saved locale category value is restored.
Definition LocaleGuard.h:47
str
String related utilities and Regular expression matching.
zypp::sat::operator=
SolvableSpec & operator=(const SolvableSpec &)=default
zypp::str::form
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition String.cc:39
zypp::str::strtonum
TInt strtonum(const C_Str &str)
Parsing numbers from string.
zypp::xmlout::node
std::ostream & node(std::ostream &out_r, const std::string &name_r, const std::initializer_list< Node::Attr > &attrs_r={})
relates: Node Write a leaf node without PCDATA
Definition Xml.h:198
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
zypp::dumpAsXmlOn
std::ostream & dumpAsXmlOn(std::ostream &str, const Repository &obj)
relates: Repository XML output
Definition Repository.cc:411
zypp::str::Str
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition String.h:213