1 //
2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #define BOOST_LOCALE_SOURCE
9 #include <boost/locale/date_time.hpp>
10 #include <boost/locale/formatting.hpp>
11 #include <boost/thread/locks.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <math.h>
14
15 namespace boost {
16 namespace locale {
17
18 using namespace period;
19
20 /////////////////////////
21 // Calendar
22 ////////////////////////
23
calendar(std::locale const & l,std::string const & zone)24 calendar::calendar(std::locale const &l,std::string const &zone) :
25 locale_(l),
26 tz_(zone),
27 impl_(std::use_facet<calendar_facet>(l).create_calendar())
28 {
29 impl_->set_timezone(tz_);
30 }
31
calendar(std::string const & zone)32 calendar::calendar(std::string const &zone) :
33 tz_(zone),
34 impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
35 {
36 impl_->set_timezone(tz_);
37 }
38
39
calendar(std::locale const & l)40 calendar::calendar(std::locale const &l) :
41 locale_(l),
42 tz_(time_zone::global()),
43 impl_(std::use_facet<calendar_facet>(l).create_calendar())
44 {
45 impl_->set_timezone(tz_);
46 }
47
calendar(std::ios_base & ios)48 calendar::calendar(std::ios_base &ios) :
49 locale_(ios.getloc()),
50 tz_(ios_info::get(ios).time_zone()),
51 impl_(std::use_facet<calendar_facet>(locale_).create_calendar())
52 {
53 impl_->set_timezone(tz_);
54
55 }
56
calendar()57 calendar::calendar() :
58 tz_(time_zone::global()),
59 impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
60 {
61 impl_->set_timezone(tz_);
62 }
63
~calendar()64 calendar::~calendar()
65 {
66 }
67
calendar(calendar const & other)68 calendar::calendar(calendar const &other) :
69 locale_(other.locale_),
70 tz_(other.tz_),
71 impl_(other.impl_->clone())
72 {
73 }
74
operator =(calendar const & other)75 calendar const &calendar::operator = (calendar const &other)
76 {
77 if(this !=&other) {
78 impl_.reset(other.impl_->clone());
79 locale_ = other.locale_;
80 tz_ = other.tz_;
81 }
82 return *this;
83 }
84
85
is_gregorian() const86 bool calendar::is_gregorian() const
87 {
88 return impl_->get_option(abstract_calendar::is_gregorian)!=0;
89 }
90
get_time_zone() const91 std::string calendar::get_time_zone() const
92 {
93 return tz_;
94 }
95
get_locale() const96 std::locale calendar::get_locale() const
97 {
98 return locale_;
99 }
100
minimum(period_type f) const101 int calendar::minimum(period_type f) const
102 {
103 return impl_->get_value(f.mark(),abstract_calendar::absolute_minimum);
104 }
105
greatest_minimum(period_type f) const106 int calendar::greatest_minimum(period_type f) const
107 {
108 return impl_->get_value(f.mark(),abstract_calendar::greatest_minimum);
109 }
110
maximum(period_type f) const111 int calendar::maximum(period_type f) const
112 {
113 return impl_->get_value(f.mark(),abstract_calendar::absolute_maximum);
114 }
115
least_maximum(period_type f) const116 int calendar::least_maximum(period_type f) const
117 {
118 return impl_->get_value(f.mark(),abstract_calendar::least_maximum);
119 }
120
first_day_of_week() const121 int calendar::first_day_of_week() const
122 {
123 return impl_->get_value(period::marks::first_day_of_week,abstract_calendar::current);
124 }
125
operator ==(calendar const & other) const126 bool calendar::operator==(calendar const &other) const
127 {
128 return impl_->same(other.impl_.get());
129 }
130
operator !=(calendar const & other) const131 bool calendar::operator!=(calendar const &other) const
132 {
133 return !(*this==other);
134 }
135
136 //////////////////////////////////
137 // date_time
138 /////////////////
139
date_time()140 date_time::date_time() :
141 impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
142 {
143 impl_->set_timezone(time_zone::global());
144 }
145
date_time(date_time const & other)146 date_time::date_time(date_time const &other)
147 {
148 impl_.reset(other.impl_->clone());
149 }
150
date_time(date_time const & other,date_time_period_set const & s)151 date_time::date_time(date_time const &other,date_time_period_set const &s)
152 {
153 impl_.reset(other.impl_->clone());
154 for(unsigned i=0;i<s.size();i++) {
155 impl_->set_value(s[i].type.mark(),s[i].value);
156 }
157 impl_->normalize();
158 }
159
operator =(date_time const & other)160 date_time const &date_time::operator = (date_time const &other)
161 {
162 if(this != &other) {
163 date_time tmp(other);
164 swap(tmp);
165 }
166 return *this;
167 }
168
~date_time()169 date_time::~date_time()
170 {
171 }
172
date_time(double t)173 date_time::date_time(double t) :
174 impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
175 {
176 impl_->set_timezone(time_zone::global());
177 time(t);
178 }
179
date_time(double t,calendar const & cal)180 date_time::date_time(double t,calendar const &cal) :
181 impl_(cal.impl_->clone())
182 {
183 time(t);
184 }
185
date_time(calendar const & cal)186 date_time::date_time(calendar const &cal) :
187 impl_(cal.impl_->clone())
188 {
189 }
190
191
192
date_time(date_time_period_set const & s)193 date_time::date_time(date_time_period_set const &s) :
194 impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
195 {
196 impl_->set_timezone(time_zone::global());
197 for(unsigned i=0;i<s.size();i++) {
198 impl_->set_value(s[i].type.mark(),s[i].value);
199 }
200 impl_->normalize();
201 }
date_time(date_time_period_set const & s,calendar const & cal)202 date_time::date_time(date_time_period_set const &s,calendar const &cal) :
203 impl_(cal.impl_->clone())
204 {
205 for(unsigned i=0;i<s.size();i++) {
206 impl_->set_value(s[i].type.mark(),s[i].value);
207 }
208 impl_->normalize();
209 }
210
operator =(date_time_period_set const & s)211 date_time const &date_time::operator=(date_time_period_set const &s)
212 {
213 for(unsigned i=0;i<s.size();i++)
214 impl_->set_value(s[i].type.mark(),s[i].value);
215 impl_->normalize();
216 return *this;
217 }
218
set(period_type f,int v)219 void date_time::set(period_type f,int v)
220 {
221 impl_->set_value(f.mark(),v);
222 impl_->normalize();
223 }
224
get(period_type f) const225 int date_time::get(period_type f) const
226 {
227 return impl_->get_value(f.mark(),abstract_calendar::current);
228 }
229
operator +(date_time_period const & v) const230 date_time date_time::operator+(date_time_period const &v) const
231 {
232 date_time tmp(*this);
233 tmp+=v;
234 return tmp;
235 }
236
operator -(date_time_period const & v) const237 date_time date_time::operator-(date_time_period const &v) const
238 {
239 date_time tmp(*this);
240 tmp-=v;
241 return tmp;
242 }
243
operator <<(date_time_period const & v) const244 date_time date_time::operator<<(date_time_period const &v) const
245 {
246 date_time tmp(*this);
247 tmp<<=v;
248 return tmp;
249 }
250
operator >>(date_time_period const & v) const251 date_time date_time::operator>>(date_time_period const &v) const
252 {
253 date_time tmp(*this);
254 tmp>>=v;
255 return tmp;
256 }
257
operator +=(date_time_period const & v)258 date_time const &date_time::operator+=(date_time_period const &v)
259 {
260 impl_->adjust_value(v.type.mark(),abstract_calendar::move,v.value);
261 return *this;
262 }
263
operator -=(date_time_period const & v)264 date_time const &date_time::operator-=(date_time_period const &v)
265 {
266 impl_->adjust_value(v.type.mark(),abstract_calendar::move,-v.value);
267 return *this;
268 }
269
operator <<=(date_time_period const & v)270 date_time const &date_time::operator<<=(date_time_period const &v)
271 {
272 impl_->adjust_value(v.type.mark(),abstract_calendar::roll,v.value);
273 return *this;
274 }
275
operator >>=(date_time_period const & v)276 date_time const &date_time::operator>>=(date_time_period const &v)
277 {
278 impl_->adjust_value(v.type.mark(),abstract_calendar::roll,-v.value);
279 return *this;
280 }
281
282
operator +(date_time_period_set const & v) const283 date_time date_time::operator+(date_time_period_set const &v) const
284 {
285 date_time tmp(*this);
286 tmp+=v;
287 return tmp;
288 }
289
operator -(date_time_period_set const & v) const290 date_time date_time::operator-(date_time_period_set const &v) const
291 {
292 date_time tmp(*this);
293 tmp-=v;
294 return tmp;
295 }
296
operator <<(date_time_period_set const & v) const297 date_time date_time::operator<<(date_time_period_set const &v) const
298 {
299 date_time tmp(*this);
300 tmp<<=v;
301 return tmp;
302 }
303
operator >>(date_time_period_set const & v) const304 date_time date_time::operator>>(date_time_period_set const &v) const
305 {
306 date_time tmp(*this);
307 tmp>>=v;
308 return tmp;
309 }
310
operator +=(date_time_period_set const & v)311 date_time const &date_time::operator+=(date_time_period_set const &v)
312 {
313 for(unsigned i=0;i<v.size();i++) {
314 *this+=v[i];
315 }
316 return *this;
317 }
318
operator -=(date_time_period_set const & v)319 date_time const &date_time::operator-=(date_time_period_set const &v)
320 {
321 for(unsigned i=0;i<v.size();i++) {
322 *this-=v[i];
323 }
324 return *this;
325 }
326
operator <<=(date_time_period_set const & v)327 date_time const &date_time::operator<<=(date_time_period_set const &v)
328 {
329 for(unsigned i=0;i<v.size();i++) {
330 *this<<=v[i];
331 }
332 return *this;
333 }
334
operator >>=(date_time_period_set const & v)335 date_time const &date_time::operator>>=(date_time_period_set const &v)
336 {
337 for(unsigned i=0;i<v.size();i++) {
338 *this>>=v[i];
339 }
340 return *this;
341 }
342
time() const343 double date_time::time() const
344 {
345 posix_time ptime = impl_->get_time();
346 return double(ptime.seconds)+1e-9*ptime.nanoseconds;
347 }
348
time(double v)349 void date_time::time(double v)
350 {
351 double dseconds = floor(v);
352 int64_t seconds = static_cast<int64_t>(dseconds);
353 double fract = v - dseconds;
354 int nano = static_cast<int>(fract * 1e9);
355 if(nano < 0)
356 nano = 0;
357 else if(nano >999999999)
358 nano = 999999999;
359 posix_time ptime;
360 ptime.seconds = seconds;
361 ptime.nanoseconds = nano;
362 impl_->set_time(ptime);
363 }
364
365 namespace {
compare(posix_time const & left,posix_time const & right)366 int compare(posix_time const &left,posix_time const &right)
367 {
368 if(left.seconds < right.seconds)
369 return -1;
370 if(left.seconds > right.seconds)
371 return 1;
372 if(left.nanoseconds < right.nanoseconds)
373 return -1;
374 if(left.nanoseconds > right.nanoseconds)
375 return 1;
376 return 0;
377 }
378 }
379
operator ==(date_time const & other) const380 bool date_time::operator==(date_time const &other) const
381 {
382 return compare(impl_->get_time(),other.impl_->get_time()) == 0;
383 }
384
operator !=(date_time const & other) const385 bool date_time::operator!=(date_time const &other) const
386 {
387 return !(*this==other);
388 }
389
operator <(date_time const & other) const390 bool date_time::operator<(date_time const &other) const
391 {
392 return compare(impl_->get_time(),other.impl_->get_time()) < 0;
393 }
394
operator >=(date_time const & other) const395 bool date_time::operator>=(date_time const &other) const
396 {
397 return !(*this<other);
398 }
399
operator >(date_time const & other) const400 bool date_time::operator>(date_time const &other) const
401 {
402 return compare(impl_->get_time(),other.impl_->get_time()) > 0;
403 }
404
operator <=(date_time const & other) const405 bool date_time::operator<=(date_time const &other) const
406 {
407 return !(*this>other);
408 }
409
swap(date_time & other)410 void date_time::swap(date_time &other)
411 {
412 impl_.swap(other.impl_);
413 }
414
difference(date_time const & other,period_type f) const415 int date_time::difference(date_time const &other,period_type f) const
416 {
417 return impl_->difference(other.impl_.get(),f.mark());
418 }
419
maximum(period_type f) const420 int date_time::maximum(period_type f) const
421 {
422 return impl_->get_value(f.mark(),abstract_calendar::actual_maximum);
423 }
424
minimum(period_type f) const425 int date_time::minimum(period_type f) const
426 {
427 return impl_->get_value(f.mark(),abstract_calendar::actual_minimum);
428 }
429
is_in_daylight_saving_time() const430 bool date_time::is_in_daylight_saving_time() const
431 {
432 return impl_->get_option(abstract_calendar::is_dst)!=0;
433 }
434
435 namespace time_zone {
tz_mutex()436 boost::mutex &tz_mutex()
437 {
438 static boost::mutex m;
439 return m;
440 }
tz_id()441 std::string &tz_id()
442 {
443 static std::string id;
444 return id;
445 }
global()446 std::string global()
447 {
448 boost::unique_lock<boost::mutex> lock(tz_mutex());
449 std::string id = tz_id();
450 return id;
451 }
global(std::string const & new_id)452 std::string global(std::string const &new_id)
453 {
454 boost::unique_lock<boost::mutex> lock(tz_mutex());
455 std::string id = tz_id();
456 tz_id() = new_id;
457 return id;
458 }
459 }
460
461
462
463 } // locale
464 } // boost
465
466
467
468 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
469
470