1 #ifndef BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__
2 #define BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__
3 
4 /* Copyright (c) 2003-2004 CrystalClear Software, Inc.
5  * Subject to the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
7  * Author: Jeff Garland, Bart Garst
8  * $Date$
9  */
10 
11 #include <locale>
12 #include <iostream>
13 #include <iterator> // i/ostreambuf_iterator
14 #include <boost/io/ios_state.hpp>
15 #include <boost/date_time/time_facet.hpp>
16 #include <boost/date_time/string_convert.hpp>
17 #include <boost/date_time/local_time/local_date_time.hpp>
18 #include <boost/date_time/local_time/posix_time_zone.hpp>
19 #include <boost/date_time/local_time/conversion.hpp> // to_tm will be needed in the facets
20 
21 namespace boost {
22 namespace local_time {
23 
24   typedef boost::date_time::time_facet<local_date_time, wchar_t> wlocal_time_facet;
25   typedef boost::date_time::time_facet<local_date_time, char>     local_time_facet;
26 
27   typedef boost::date_time::time_input_facet<local_date_time::utc_time_type,wchar_t> wlocal_time_input_facet;
28   typedef boost::date_time::time_input_facet<local_date_time::utc_time_type,char>     local_time_input_facet;
29 
30   //! operator<< for local_date_time - see local_time docs for formatting details
31   template<class CharT, class TraitsT>
32   inline
33   std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT,TraitsT> & os,const local_date_time & ldt)34   operator<<(std::basic_ostream<CharT, TraitsT>& os, const local_date_time& ldt)
35   {
36     boost::io::ios_flags_saver iflags(os);
37     typedef local_date_time time_type;//::utc_time_type typename
38     typedef date_time::time_facet<time_type, CharT> custom_time_facet;
39     std::ostreambuf_iterator<CharT> oitr(os);
40 
41     if(std::has_facet<custom_time_facet>(os.getloc())) {
42       std::use_facet<custom_time_facet>(os.getloc()).put(oitr,
43                                                          os,
44                                                          os.fill(),
45                                                          ldt);
46     }
47     else {
48       custom_time_facet* f = new custom_time_facet();
49       std::locale l = std::locale(os.getloc(), f);
50       os.imbue(l);
51       f->put(oitr, os, os.fill(), ldt);
52     }
53 
54     return os;
55   }
56 
57 
58   //! input operator for local_date_time
59   template <class CharT, class Traits>
60   inline
61   std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,local_date_time & ldt)62   operator>>(std::basic_istream<CharT, Traits>& is, local_date_time& ldt)
63   {
64     boost::io::ios_flags_saver iflags(is);
65     typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
66     if (strm_sentry) {
67       try {
68         typedef typename local_date_time::utc_time_type utc_time_type;
69         typedef typename date_time::time_input_facet<utc_time_type, CharT> time_input_facet;
70 
71         // intermediate objects
72         std::basic_string<CharT> tz_str;
73         utc_time_type pt(not_a_date_time);
74 
75         std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
76         if(std::has_facet<time_input_facet>(is.getloc())) {
77           std::use_facet<time_input_facet>(is.getloc()).get_local_time(sit, str_end, is, pt, tz_str);
78         }
79         else {
80           time_input_facet* f = new time_input_facet();
81           std::locale l = std::locale(is.getloc(), f);
82           is.imbue(l);
83           f->get_local_time(sit, str_end, is, pt, tz_str);
84         }
85         if(tz_str.empty()) {
86           time_zone_ptr null_ptr;
87           // a null time_zone_ptr creates a local_date_time that is UTC
88           ldt = local_date_time(pt, null_ptr);
89         }
90         else {
91           time_zone_ptr tz_ptr(new posix_time_zone(date_time::convert_string_type<CharT,char>(tz_str)));
92           // the "date & time" constructor expects the time label to *not* be utc.
93           // a posix_tz_string also expects the time label to *not* be utc.
94           ldt = local_date_time(pt.date(), pt.time_of_day(), tz_ptr, local_date_time::EXCEPTION_ON_ERROR);
95         }
96       }
97       catch(...) {
98         // mask tells us what exceptions are turned on
99         std::ios_base::iostate exception_mask = is.exceptions();
100         // if the user wants exceptions on failbit, we'll rethrow our
101         // date_time exception & set the failbit
102         if(std::ios_base::failbit & exception_mask) {
103           try { is.setstate(std::ios_base::failbit); }
104           catch(std::ios_base::failure&) {} // ignore this one
105           throw; // rethrow original exception
106         }
107         else {
108           // if the user want's to fail quietly, we simply set the failbit
109           is.setstate(std::ios_base::failbit);
110         }
111 
112       }
113     }
114     return is;
115   }
116 
117   //! output operator for local_time_period
118   template <class CharT, class TraitsT>
119   inline
120   std::basic_ostream<CharT, TraitsT>&
operator <<(std::basic_ostream<CharT,TraitsT> & os,const boost::local_time::local_time_period & p)121   operator<<(std::basic_ostream<CharT, TraitsT>& os,
122              const boost::local_time::local_time_period& p) {
123     boost::io::ios_flags_saver iflags(os);
124     typedef boost::date_time::time_facet<local_date_time, CharT> custom_facet;
125     std::ostreambuf_iterator<CharT> oitr(os);
126     if (std::has_facet<custom_facet>(os.getloc())) {
127       std::use_facet<custom_facet>(os.getloc()).put(oitr, os, os.fill(), p);
128     }
129     else {
130       //instantiate a custom facet for dealing with periods since the user
131       //has not put one in the stream so far.  This is for efficiency
132       //since we would always need to reconstruct for every time period
133       //if the local did not already exist.  Of course this will be overridden
134       //if the user imbues as some later point.
135       custom_facet* f = new custom_facet();
136       std::locale l = std::locale(os.getloc(), f);
137       os.imbue(l);
138       f->put(oitr, os, os.fill(), p);
139     }
140     return os;
141   }
142 
143   //! input operator for local_time_period
144   template <class CharT, class Traits>
145   inline
146   std::basic_istream<CharT, Traits>&
operator >>(std::basic_istream<CharT,Traits> & is,boost::local_time::local_time_period & tp)147   operator>>(std::basic_istream<CharT, Traits>& is, boost::local_time::local_time_period& tp)
148   {
149     boost::io::ios_flags_saver iflags(is);
150     typename std::basic_istream<CharT, Traits>::sentry strm_sentry(is, false);
151     if (strm_sentry) {
152       try {
153         typedef typename date_time::time_input_facet<local_date_time, CharT> time_input_facet;
154 
155         std::istreambuf_iterator<CharT,Traits> sit(is), str_end;
156         if(std::has_facet<time_input_facet>(is.getloc())) {
157           std::use_facet<time_input_facet>(is.getloc()).get(sit, str_end, is, tp);
158         }
159         else {
160           time_input_facet* f = new time_input_facet();
161           std::locale l = std::locale(is.getloc(), f);
162           is.imbue(l);
163           f->get(sit, str_end, is, tp);
164         }
165       }
166       catch(...) {
167         std::ios_base::iostate exception_mask = is.exceptions();
168         if(std::ios_base::failbit & exception_mask) {
169           try { is.setstate(std::ios_base::failbit); }
170           catch(std::ios_base::failure&) {}
171           throw; // rethrow original exception
172         }
173         else {
174           is.setstate(std::ios_base::failbit);
175         }
176 
177       }
178     }
179     return is;
180   }
181 
182 } } // namespaces
183 
184 #endif // BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__
185