ome-xml  5.6.0
Timestamp.h
1 /*
2  * #%L
3  * OME-XML C++ library for working with OME-XML metadata structures.
4  * %%
5  * Copyright © 2006 - 2016 Open Microscopy Environment:
6  * - Massachusetts Institute of Technology
7  * - National Institutes of Health
8  * - University of Dundee
9  * - Board of Regents of the University of Wisconsin-Madison
10  * - Glencoe Software, Inc.
11  * %%
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  * this list of conditions and the following disclaimer in the documentation
19  * and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * The views and conclusions contained in the software and documentation are
34  * those of the authors and should not be interpreted as representing official
35  * policies, either expressed or implied, of any organization.
36  * #L%
37  */
38 
39 #ifndef OME_XML_MODEL_PRIMITIVES_TIMESTAMP_H
40 #define OME_XML_MODEL_PRIMITIVES_TIMESTAMP_H
41 
42 #include <cstdint>
43 #include <string>
44 #include <sstream>
45 #include <stdexcept>
46 
47 #include <boost/date_time/posix_time/posix_time.hpp>
48 
49 namespace ome
50 {
51  namespace xml
52  {
53  namespace model
54  {
55  namespace primitives
56  {
57 
65  class Timestamp {
66  public:
68  typedef boost::posix_time::ptime value_type;
69 
73  Timestamp();
74 
80  Timestamp(const std::string& value);
81 
87  Timestamp(value_type value);
88 
94  inline
95  operator value_type () const
96  {
97  return this->value;
98  }
99 
100  private:
102  value_type value;
103  };
104 
112  template<class charT, class traits>
113  inline std::basic_ostream<charT,traits>&
114  operator<< (std::basic_ostream<charT,traits>& os,
115  const Timestamp& timestamp)
116  {
117  return os << boost::posix_time::to_iso_extended_string(static_cast<Timestamp::value_type>(timestamp))
118  << 'Z';
119  }
120 
128  template<class charT, class traits>
129  inline std::basic_istream<charT,traits>&
130  operator>> (std::basic_istream<charT,traits>& is,
131  Timestamp& timestamp)
132  {
133  std::istream::sentry s(is);
134  if (s)
135  {
137 
138  // Save locale.
139  std::locale savedlocale = is.getloc();
140 
141  try
142  {
143  boost::posix_time::time_input_facet *input_facet =
144  new boost::posix_time::time_input_facet();
145  input_facet->set_iso_extended_format();
146  std::locale iso8601_loc(std::locale::classic(), input_facet);
147 
148  is.imbue(iso8601_loc);
149  is >> value;
150 
151  if (is)
152  {
153  // Check for zone offset
154  std::char_traits<char>::int_type tztype = is.peek();
155  if(tztype != std::char_traits<char>::eof())
156  {
157  if (tztype == 'Z')
158  {
159  is.ignore(); // Drop above from istream
160  // If Z, we're already using UTC, so don't apply numeric offsets
161  }
162  else if (tztype == '-' || tztype == '+')
163  {
164  is.ignore(); // Drop above from istream
165  if (is.rdbuf()->in_avail() >= 4) // Need 4 numeric chars
166  {
167  // Check that the next 4 characters are only numeric
168  std::string inchars(4, ' ');
169  is.read(&inchars[0], 4);
170  for (const auto& i : inchars)
171  if (i < '0' || i > '9')
172  is.setstate(std::ios::failbit);
173 
174  if (is)
175  {
176  // Get offset value
177  int offset;
178  std::istringstream valueis(inchars);
179  valueis >> offset;
180  if (valueis)
181  {
182  if (tztype == '+')
183  offset = -offset;
184  // Offset in hours, minutes, seconds
185  boost::posix_time::time_duration d(offset/100, offset%100, 0);
186  // Apply offset
187  value += d;
188  }
189  else
190  is.setstate(std::ios::failbit);
191  }
192  }
193  else
194  {
195  is.setstate(std::ios::failbit);
196  }
197  }
198  }
199  }
200 
201  if (is)
202  timestamp = Timestamp(value);
203  else
204  throw std::runtime_error("Failed to parse timestamp");
205  }
206  catch (const std::exception& e)
207  {
208  is.imbue(savedlocale);
209  throw;
210  }
211 
212  is.imbue(savedlocale);
213  }
214  return is;
215  }
216 
217  }
218  }
219  }
220 }
221 
222 #endif // OME_XML_MODEL_PRIMITIVES_TIMESTAMP_H
223 
224 /*
225  * Local Variables:
226  * mode:C++
227  * End:
228  */
An ISO-8601 timestamp.
Definition: Timestamp.h:65
value_type value
The POSIX time (at least microsecond precision).
Definition: Timestamp.h:102
Timestamp()
Construct a Timestamp (defaults to current UTC time).
Definition: Timestamp.cpp:50
Open Microscopy Environment C++ implementation.
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &is, Color &color)
Set Color from input stream.
Definition: Color.h:478
boost::posix_time::ptime value_type
POSIX time is the underlying time representation.
Definition: Timestamp.h:68