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/mutex.hpp>
12 #include <math.h>
13 
14 namespace boost {
15 namespace locale {
16 
17 using namespace period;
18 
19 /////////////////////////
20 // Calendar
21 ////////////////////////
22 
calendar(std::locale const & l,std::string const & zone)23 calendar::calendar(std::locale const &l,std::string const &zone) :
24     locale_(l),
25     tz_(zone),
26     impl_(std::use_facet<calendar_facet>(l).create_calendar())
27 {
28     impl_->set_timezone(tz_);
29 }
30 
calendar(std::string const & zone)31 calendar::calendar(std::string const &zone) :
32     tz_(zone),
33     impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
34 {
35     impl_->set_timezone(tz_);
36 }
37 
38 
calendar(std::locale const & l)39 calendar::calendar(std::locale const &l) :
40     locale_(l),
41     tz_(time_zone::global()),
42     impl_(std::use_facet<calendar_facet>(l).create_calendar())
43 {
44     impl_->set_timezone(tz_);
45 }
46 
calendar(std::ios_base & ios)47 calendar::calendar(std::ios_base &ios) :
48     locale_(ios.getloc()),
49     tz_(ios_info::get(ios).time_zone()),
50     impl_(std::use_facet<calendar_facet>(locale_).create_calendar())
51 {
52     impl_->set_timezone(tz_);
53 
54 }
55 
calendar()56 calendar::calendar() :
57     tz_(time_zone::global()),
58     impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
59 {
60     impl_->set_timezone(tz_);
61 }
62 
~calendar()63 calendar::~calendar()
64 {
65 }
66 
calendar(calendar const & other)67 calendar::calendar(calendar const &other) :
68     locale_(other.locale_),
69     tz_(other.tz_),
70     impl_(other.impl_->clone())
71 {
72 }
73 
operator =(calendar const & other)74 calendar const &calendar::operator = (calendar const &other)
75 {
76     if(this !=&other) {
77         impl_.reset(other.impl_->clone());
78         locale_ = other.locale_;
79         tz_ = other.tz_;
80     }
81     return *this;
82 }
83 
84 
is_gregorian() const85 bool calendar::is_gregorian() const
86 {
87     return impl_->get_option(abstract_calendar::is_gregorian)!=0;
88 }
89 
get_time_zone() const90 std::string calendar::get_time_zone() const
91 {
92     return tz_;
93 }
94 
get_locale() const95 std::locale calendar::get_locale() const
96 {
97     return locale_;
98 }
99 
minimum(period_type f) const100 int calendar::minimum(period_type f) const
101 {
102     return impl_->get_value(f.mark(),abstract_calendar::absolute_minimum);
103 }
104 
greatest_minimum(period_type f) const105 int calendar::greatest_minimum(period_type f) const
106 {
107     return impl_->get_value(f.mark(),abstract_calendar::greatest_minimum);
108 }
109 
maximum(period_type f) const110 int calendar::maximum(period_type f) const
111 {
112     return impl_->get_value(f.mark(),abstract_calendar::absolute_maximum);
113 }
114 
least_maximum(period_type f) const115 int calendar::least_maximum(period_type f) const
116 {
117     return impl_->get_value(f.mark(),abstract_calendar::least_maximum);
118 }
119 
first_day_of_week() const120 int calendar::first_day_of_week() const
121 {
122     return impl_->get_value(period::marks::first_day_of_week,abstract_calendar::current);
123 }
124 
operator ==(calendar const & other) const125 bool calendar::operator==(calendar const &other) const
126 {
127     return impl_->same(other.impl_.get());
128 }
129 
operator !=(calendar const & other) const130 bool calendar::operator!=(calendar const &other) const
131 {
132     return !(*this==other);
133 }
134 
135 //////////////////////////////////
136 // date_time
137 /////////////////
138 
date_time()139 date_time::date_time() :
140     impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
141 {
142     impl_->set_timezone(time_zone::global());
143 }
144 
date_time(date_time const & other)145 date_time::date_time(date_time const &other)
146 {
147     impl_.reset(other.impl_->clone());
148 }
149 
date_time(date_time const & other,date_time_period_set const & s)150 date_time::date_time(date_time const &other,date_time_period_set const &s)
151 {
152     impl_.reset(other.impl_->clone());
153     for(unsigned i=0;i<s.size();i++) {
154         impl_->set_value(s[i].type.mark(),s[i].value);
155     }
156     impl_->normalize();
157 }
158 
operator =(date_time const & other)159 date_time const &date_time::operator = (date_time const &other)
160 {
161     if(this != &other) {
162         date_time tmp(other);
163         swap(tmp);
164     }
165     return *this;
166 }
167 
~date_time()168 date_time::~date_time()
169 {
170 }
171 
date_time(double t)172 date_time::date_time(double t) :
173     impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
174 {
175     impl_->set_timezone(time_zone::global());
176     time(t);
177 }
178 
date_time(double t,calendar const & cal)179 date_time::date_time(double t,calendar const &cal) :
180     impl_(cal.impl_->clone())
181 {
182     time(t);
183 }
184 
date_time(calendar const & cal)185 date_time::date_time(calendar const &cal) :
186     impl_(cal.impl_->clone())
187 {
188 }
189 
190 
191 
date_time(date_time_period_set const & s)192 date_time::date_time(date_time_period_set const &s) :
193     impl_(std::use_facet<calendar_facet>(std::locale()).create_calendar())
194 {
195     impl_->set_timezone(time_zone::global());
196     for(unsigned i=0;i<s.size();i++) {
197         impl_->set_value(s[i].type.mark(),s[i].value);
198     }
199     impl_->normalize();
200 }
date_time(date_time_period_set const & s,calendar const & cal)201 date_time::date_time(date_time_period_set const &s,calendar const &cal) :
202     impl_(cal.impl_->clone())
203 {
204     for(unsigned i=0;i<s.size();i++) {
205         impl_->set_value(s[i].type.mark(),s[i].value);
206     }
207     impl_->normalize();
208 }
209 
operator =(date_time_period_set const & s)210 date_time const &date_time::operator=(date_time_period_set const &s)
211 {
212     for(unsigned i=0;i<s.size();i++)
213         impl_->set_value(s[i].type.mark(),s[i].value);
214     impl_->normalize();
215     return *this;
216 }
217 
set(period_type f,int v)218 void date_time::set(period_type f,int v)
219 {
220     impl_->set_value(f.mark(),v);
221     impl_->normalize();
222 }
223 
get(period_type f) const224 int date_time::get(period_type f) const
225 {
226     return impl_->get_value(f.mark(),abstract_calendar::current);
227 }
228 
operator +(date_time_period const & v) const229 date_time date_time::operator+(date_time_period const &v) const
230 {
231     date_time tmp(*this);
232     tmp+=v;
233     return tmp;
234 }
235 
operator -(date_time_period const & v) const236 date_time date_time::operator-(date_time_period const &v) const
237 {
238     date_time tmp(*this);
239     tmp-=v;
240     return tmp;
241 }
242 
operator <<(date_time_period const & v) const243 date_time date_time::operator<<(date_time_period const &v) const
244 {
245     date_time tmp(*this);
246     tmp<<=v;
247     return tmp;
248 }
249 
operator >>(date_time_period const & v) const250 date_time date_time::operator>>(date_time_period const &v) const
251 {
252     date_time tmp(*this);
253     tmp>>=v;
254     return tmp;
255 }
256 
operator +=(date_time_period const & v)257 date_time const &date_time::operator+=(date_time_period const &v)
258 {
259     impl_->adjust_value(v.type.mark(),abstract_calendar::move,v.value);
260     return *this;
261 }
262 
operator -=(date_time_period const & v)263 date_time const &date_time::operator-=(date_time_period const &v)
264 {
265     impl_->adjust_value(v.type.mark(),abstract_calendar::move,-v.value);
266     return *this;
267 }
268 
operator <<=(date_time_period const & v)269 date_time const &date_time::operator<<=(date_time_period const &v)
270 {
271     impl_->adjust_value(v.type.mark(),abstract_calendar::roll,v.value);
272     return *this;
273 }
274 
operator >>=(date_time_period const & v)275 date_time const &date_time::operator>>=(date_time_period const &v)
276 {
277     impl_->adjust_value(v.type.mark(),abstract_calendar::roll,-v.value);
278     return *this;
279 }
280 
281 
operator +(date_time_period_set const & v) const282 date_time date_time::operator+(date_time_period_set const &v) const
283 {
284     date_time tmp(*this);
285     tmp+=v;
286     return tmp;
287 }
288 
operator -(date_time_period_set const & v) const289 date_time date_time::operator-(date_time_period_set const &v) const
290 {
291     date_time tmp(*this);
292     tmp-=v;
293     return tmp;
294 }
295 
operator <<(date_time_period_set const & v) const296 date_time date_time::operator<<(date_time_period_set const &v) const
297 {
298     date_time tmp(*this);
299     tmp<<=v;
300     return tmp;
301 }
302 
operator >>(date_time_period_set const & v) const303 date_time date_time::operator>>(date_time_period_set const &v) const
304 {
305     date_time tmp(*this);
306     tmp>>=v;
307     return tmp;
308 }
309 
operator +=(date_time_period_set const & v)310 date_time const &date_time::operator+=(date_time_period_set const &v)
311 {
312     for(unsigned i=0;i<v.size();i++) {
313         *this+=v[i];
314     }
315     return *this;
316 }
317 
operator -=(date_time_period_set const & v)318 date_time const &date_time::operator-=(date_time_period_set const &v)
319 {
320     for(unsigned i=0;i<v.size();i++) {
321         *this-=v[i];
322     }
323     return *this;
324 }
325 
operator <<=(date_time_period_set const & v)326 date_time const &date_time::operator<<=(date_time_period_set const &v)
327 {
328     for(unsigned i=0;i<v.size();i++) {
329         *this<<=v[i];
330     }
331     return *this;
332 }
333 
operator >>=(date_time_period_set const & v)334 date_time const &date_time::operator>>=(date_time_period_set const &v)
335 {
336     for(unsigned i=0;i<v.size();i++) {
337         *this>>=v[i];
338     }
339     return *this;
340 }
341 
time() const342 double date_time::time() const
343 {
344     posix_time ptime = impl_->get_time();
345     return double(ptime.seconds)+1e-9*ptime.nanoseconds;
346 }
347 
time(double v)348 void date_time::time(double v)
349 {
350     double dseconds = floor(v);
351     int64_t seconds = static_cast<int64_t>(dseconds);
352     double fract = v - dseconds;
353     int nano = static_cast<int>(fract * 1e9);
354     if(nano < 0)
355         nano = 0;
356     else if(nano >999999999)
357         nano = 999999999;
358     posix_time ptime;
359     ptime.seconds = seconds;
360     ptime.nanoseconds = nano;
361     impl_->set_time(ptime);
362 }
363 
364 namespace {
compare(posix_time const & left,posix_time const & right)365     int compare(posix_time const &left,posix_time const &right)
366     {
367         if(left.seconds < right.seconds)
368             return -1;
369         if(left.seconds > right.seconds)
370             return 1;
371         if(left.nanoseconds < right.nanoseconds)
372             return -1;
373         if(left.nanoseconds > right.nanoseconds)
374             return 1;
375         return 0;
376     }
377 }
378 
operator ==(date_time const & other) const379 bool date_time::operator==(date_time const &other) const
380 {
381     return compare(impl_->get_time(),other.impl_->get_time()) == 0;
382 }
383 
operator !=(date_time const & other) const384 bool date_time::operator!=(date_time const &other) const
385 {
386     return !(*this==other);
387 }
388 
operator <(date_time const & other) const389 bool date_time::operator<(date_time const &other) const
390 {
391     return compare(impl_->get_time(),other.impl_->get_time()) < 0;
392 }
393 
operator >=(date_time const & other) const394 bool date_time::operator>=(date_time const &other) const
395 {
396     return !(*this<other);
397 }
398 
operator >(date_time const & other) const399 bool date_time::operator>(date_time const &other) const
400 {
401     return compare(impl_->get_time(),other.impl_->get_time()) > 0;
402 }
403 
operator <=(date_time const & other) const404 bool date_time::operator<=(date_time const &other) const
405 {
406     return !(*this>other);
407 }
408 
swap(date_time & other)409 void date_time::swap(date_time &other)
410 {
411     impl_.swap(other.impl_);
412 }
413 
difference(date_time const & other,period_type f) const414 int date_time::difference(date_time const &other,period_type f) const
415 {
416     return impl_->difference(other.impl_.get(),f.mark());
417 }
418 
maximum(period_type f) const419 int date_time::maximum(period_type f) const
420 {
421     return impl_->get_value(f.mark(),abstract_calendar::actual_maximum);
422 }
423 
minimum(period_type f) const424 int date_time::minimum(period_type f) const
425 {
426     return impl_->get_value(f.mark(),abstract_calendar::actual_minimum);
427 }
428 
is_in_daylight_saving_time() const429 bool date_time::is_in_daylight_saving_time() const
430 {
431     return impl_->get_option(abstract_calendar::is_dst)!=0;
432 }
433 
434 namespace time_zone {
tz_mutex()435     boost::mutex &tz_mutex()
436     {
437         static boost::mutex m;
438         return m;
439     }
tz_id()440     std::string &tz_id()
441     {
442         static std::string id;
443         return id;
444     }
global()445     std::string global()
446     {
447         boost::unique_lock<boost::mutex> lock(tz_mutex());
448         std::string id = tz_id();
449         return id;
450     }
global(std::string const & new_id)451     std::string global(std::string const &new_id)
452     {
453         boost::unique_lock<boost::mutex> lock(tz_mutex());
454         std::string id = tz_id();
455         tz_id() = new_id;
456         return id;
457     }
458 }
459 
460 
461 
462 } // locale
463 } // boost
464 
465 
466 
467 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
468 
469