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