Jpp  master_rocky-37-gf0c5bc59d
the software that should make you happy
JDateAndTime.hh
Go to the documentation of this file.
1 #ifndef __JSYSTEM__JDATEANDTIME__
2 #define __JSYSTEM__JDATEANDTIME__
3 
4 #include <istream>
5 #include <ostream>
6 #include <sstream>
7 #include <string>
8 #include <string.h>
9 #include <time.h>
10 
11 #include "JLang/JComparable.hh"
12 #include "JLang/JException.hh"
13 
14 
15 /**
16  * \file
17  * Date and time functions.
18  *
19  * \author mdejong, bjung
20  */
21 namespace JSYSTEM {}
22 namespace JPP { using namespace JSYSTEM; }
23 
24 namespace JSYSTEM {
25 
26  using JLANG::JComparable;
27  using JLANG::JIOException;
28  using JLANG::JParseError;
29 
30 
31  /**
32  * Get current local date conform ISO-8601 standard.
33  *
34  * \return date
35  */
36  inline const char* getDate()
37  {
38  static time_t ts;
39  static const size_t MAX_SIZE = 256;
40  static char buffer[MAX_SIZE];
41 
42  time(&ts);
43 
44  strftime(buffer, MAX_SIZE, "%F", localtime(&ts));
45 
46  return buffer;
47  }
48 
49 
50  /**
51  * Get current local time conform ISO-8601 standard.
52  *
53  * \return time
54  */
55  inline const char* getTime()
56  {
57  static time_t ts;
58  static const size_t MAX_SIZE = 256;
59  static char buffer[MAX_SIZE];
60 
61  time(&ts);
62 
63  strftime(buffer, MAX_SIZE, "%T%z", localtime(&ts));
64 
65  return buffer;
66  }
67 
68 
69  /**
70  * Auxiliary class for date and time.
71  *
72  * The data structure <tt>time_t</tt> is used for the internal value and
73  * the data structure <tt>tm</tt> for the representation.
74  *
75  * The I/O format conforms with ISO-8601 standard
76  * but it is also possible to parse <tt>ROOT TTimeStamp::AsString("c")</tt>.
77  */
78  struct JDateAndTime :
79  JComparable<JDateAndTime>
80  {
81  /**
82  * Constructor.
83  *
84  * \param utc UTC
85  */
86  JDateAndTime(const bool utc = false)
87  {
88  set(utc);
89  }
90 
91 
92  /**
93  * Constructor.
94  *
95  * \param t1 time [s]
96  * \param utc UTC
97  */
98  JDateAndTime(const time_t t1, const bool utc = false)
99  {
100  set(t1, utc);
101  }
102 
103 
104  /**
105  * Constructor.
106  *
107  * \param t1 time [s]
108  * \param f1 fraction of seconds
109  * \param utc UTC
110  */
111  JDateAndTime(const time_t t1, const float f1, const bool utc = false)
112  {
113  set(t1, f1, utc);
114  }
115 
116 
117  /**
118  * Constructor.
119  *
120  * \param buffer date and time
121  */
122  JDateAndTime(const std::string& buffer)
123  {
124  std::istringstream is(buffer);
125 
126  is >> *this;
127  }
128 
129 
130  /**
131  * Less than method.
132  *
133  * \param object date and time
134  * \result true if this date and time is less than given data and time; else false
135  */
136  inline bool less(const JDateAndTime& object) const
137  {
138  return getElapsedTime(object) > 0.0;
139  }
140 
141 
142  /**
143  * Smart pointer.
144  *
145  * \return pointer to time structure
146  */
147  const tm* operator->() const
148  {
149  return get();
150  }
151 
152 
153  /**
154  * Check if UTC time.
155  *
156  * \return true if UTC time; else false
157  */
158  bool isUTC() const
159  {
160  return utc;
161  }
162 
163 
164  time_t getTime() const { return ts; } //!< time
165 
166  int getSeconds() const { return get()->tm_sec; } //!< seconds after the minute [0-59]
167  int getMinutes() const { return get()->tm_min; } //!< minutes after the hour [0-59]
168  int getHour() const { return get()->tm_hour; } //!< hours after midnight [0-23]
169  int getDay() const { return get()->tm_mday; } //!< day of the month [1-31]
170  int getMonth() const { return get()->tm_mon + 1; } //!< month of the year [1-12]
171  int getYear() const { return get()->tm_year + 1900; } //!< year a.d.
172  int getDST() const { return get()->tm_isdst; } //!< daylight saving time
173 
174  float getFS() const { return fs; } //!< fraction of second
175 
176 
177  /**
178  * Type conversion operator.
179  *
180  * \return ASCII formatted date and time
181  */
182  operator std::string() const
183  {
184  return this->toString();
185  }
186 
187 
188  /**
189  * Function to check ISO-8601 conformity.
190  *
191  * \param buffer date and time
192  * \return true if date and time are ISO-8601 conform; else false
193  */
194  inline static bool isISO8601(const std::string& buffer)
195  {
196  using namespace std;
197 
198  try {
199 
200  JDateAndTime t1(buffer);
201 
202  return true;
203  }
204  catch(const std::exception& error) {
205  return false;
206  }
207  }
208 
209 
210  /**
211  * Get ASCII formatted date and time.
212  *
213  * \return ASCII formatted date and time
214  */
215  inline std::string toString() const
216  {
217  using namespace std;
218 
219  static const size_t MAX_SIZE = 256;
220  static char buffer[MAX_SIZE];
221 
222  const size_t pos = strftime(buffer, MAX_SIZE, (isUTC() ? "%FT%TZ" : "%FT%T%z"), this->get());
223 
224  return string(buffer, pos);
225  }
226 
227 
228  /**
229  * Set date and time.
230  *
231  * \return date and time
232  */
233  inline const JDateAndTime& operator()()
234  {
235  set();
236 
237  return *this;
238  }
239 
240 
241  /**
242  * Set to current local time.
243  *
244  * \param utc UTC
245  */
246  void set(const bool utc = false)
247  {
248  time_t tx;
249 
250  time(&tx);
251 
252  set(tx, utc);
253  }
254 
255 
256  /**
257  * Set to given time.
258  *
259  * \param t1 time [s]
260  * \param utc UTC
261  */
262  void set(const time_t t1, const bool utc = false)
263  {
264  this->ts = t1;
265  this->utc = utc;
266  }
267 
268 
269  /**
270  * Set to given time.
271  *
272  * \param t1 time [s]
273  * \param f1 fraction of seconds
274  * \param utc UTC
275  */
276  void set(const time_t t1, const float f1, const bool utc = false)
277  {
278  this->ts = t1;
279  this->fs = f1;
280  this->utc = utc;
281  }
282 
283 
284  /**
285  * Add given time.
286  *
287  * \param t1 time [s]
288  */
289  void add(const time_t t1)
290  {
291  set(this->ts + t1, this->utc);
292  }
293 
294 
295  /**
296  * Subtract given time.
297  *
298  * \param t1 time [s]
299  */
300  void sub(const time_t t1)
301  {
302  set(this->ts - t1, this->utc);
303  }
304 
305 
306  /**
307  * Get elapsed time to given date and time.
308  *
309  * \param object date and time
310  * \return time [s]
311  */
312  double getElapsedTime(const JDateAndTime& object) const
313  {
314  return difftime(object.ts, this->ts) + (object.fs - this->fs);
315  }
316 
317 
318  /**
319  * Read date and time from input stream.
320  *
321  * \param in input stream
322  * \param object date and time
323  * \return input stream
324  */
325  friend inline std::istream& operator>>(std::istream& in, JDateAndTime& object)
326  {
327  using namespace std;
328 
329  const size_t LENGTH = 10; // date may contain '-' and/or be followed by ' '
330 
331  string buffer;
332 
333  for (int c; (c = in.peek()) != EOF && isspace((char) in.peek()); ) {
334  in.ignore(1);
335  }
336 
337  for (int c; (c = in.get()) != EOF && (c != ' ' || buffer.length() == LENGTH); ) {
338  buffer.push_back((char) c);
339  }
340 
341  if (in.bad()) {
342  THROW(JIOException, "");
343  }
344 
345  // separation of date and time from optional time zone
346 
347  size_t pos = string::npos;
348 
349  if (pos == string::npos) { pos = buffer.find('Z', LENGTH); } // UTC
350  if (pos == string::npos) { pos = buffer.find('+', LENGTH); } // optional time zone
351  if (pos == string::npos) { pos = buffer.find('-', LENGTH); } // optional time zone
352 
353  tm tx;
354  object.fs = 0; // fraction of seconds
355  int nd = 0;
356 
357  const string td = buffer.substr(0, pos);
358  const char* pd = NULL;
359 
360  switch (td.length()) {
361 
362  case 29:
363  case 28:
364  case 27:
365  case 26:
366  case 25:
367  case 24:
368  case 23:
369  case 22:
370  case 21:
371  pd = strptime(td.c_str(), "%Y-%m-%d %H:%M:%S", &tx); sscanf(pd, "%f%n", &object.fs, &nd); pd += nd;
372  break;
373 
374  case 19:
375  pd = strptime(td.c_str(), "%Y-%m-%dT%H:%M:%S", &tx);
376  break;
377 
378  case 15:
379  pd = strptime(td.c_str(), "%Y%m%dT%H%M%s", &tx);
380  break;
381 
382  case 10:
383  pd = strptime(td.c_str(), "%Y-%m-%d", &tx);
384  break;
385  }
386 
387  if (pd == NULL || *pd != '\0') {
388  THROW(JParseError, "invalid input <" << buffer << ">");
389  }
390 
391  tm ty;
392 
393  ty.tm_hour = 0;
394  ty.tm_min = 0;
395 
396  if (pos != string::npos && (buffer[pos] == '+' ||
397  buffer[pos] == '-')) {
398 
399  const string tz = buffer.substr(pos + 1);
400  const char* pz = tz.c_str();
401 
402  switch (tz.length()) {
403 
404  case 2:
405  pz = strptime(tz.c_str(), "%H", &ty);
406  break;
407 
408  case 4:
409  pz = strptime(tz.c_str(), "%H%M", &ty);
410  break;
411 
412  case 5:
413  pz = strptime(tz.c_str(), "%H:%M", &ty);
414  break;
415  }
416 
417  if (pz == NULL || *pz != '\0') {
418  THROW(JParseError, "invalid input <" << buffer << ">");
419  }
420  }
421 
422  tx.tm_isdst = 0; // switch off day light saving time
423 
424  time_t t1 = mktime(&tx);
425 
426  t1 -= (ty.tm_hour * 60 + ty.tm_min) * 60; // correct time zone
427  t1 += mktime(localtime(&t1)) - mktime(gmtime(&t1)); //
428 
429  object.set(t1, buffer[pos] == 'Z');
430 
431  return in;
432  }
433 
434 
435  /**
436  * Write date and time to output stream.
437  *
438  * \param out output stream
439  * \param object date and time
440  * \return output stream
441  */
442  friend inline std::ostream& operator<<(std::ostream& out, const JDateAndTime& object)
443  {
444  return out << object.toString();
445  }
446 
447 
448  private:
449 
450  /**
451  * Get representation.
452  */
453  tm* get() const
454  {
455  return (this->tp = (utc ? gmtime(&ts) : localtime(&ts)));
456  }
457 
458  time_t ts; //!< value
459  float fs = 0.0; //!< fraction of second
460  mutable tm* tp; //!< representation
461  bool utc = false; //!< UTC
462  };
463 
464 
465  /**
466  * Function object to get current date and time.
467  */
469 }
470 
471 #endif
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
Exception for I/O.
Definition: JException.hh:342
Exception for parsing value.
Definition: JException.hh:198
const JPolynome f1(1.0, 2.0, 3.0)
Function.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
Auxiliary classes and methods for operating system calls.
Definition: JDateAndTime.hh:21
const char * getTime()
Get current local time conform ISO-8601 standard.
Definition: JDateAndTime.hh:55
static JDateAndTime getDateAndTime
Function object to get current date and time.
const char * getDate()
Get current local date conform ISO-8601 standard.
Definition: JDateAndTime.hh:36
Definition: JSTDTypes.hh:14
Template definition of auxiliary base class for comparison of data structures.
Definition: JComparable.hh:139
Auxiliary class for date and time.
Definition: JDateAndTime.hh:80
JDateAndTime(const bool utc=false)
Constructor.
Definition: JDateAndTime.hh:86
bool isUTC() const
Check if UTC time.
double getElapsedTime(const JDateAndTime &object) const
Get elapsed time to given date and time.
friend std::ostream & operator<<(std::ostream &out, const JDateAndTime &object)
Write date and time to output stream.
JDateAndTime(const std::string &buffer)
Constructor.
std::string toString() const
Get ASCII formatted date and time.
JDateAndTime(const time_t t1, const float f1, const bool utc=false)
Constructor.
int getMinutes() const
minutes after the hour [0-59]
int getYear() const
year a.d.
time_t getTime() const
time
int getHour() const
hours after midnight [0-23]
int getDST() const
daylight saving time
void set(const bool utc=false)
Set to current local time.
bool less(const JDateAndTime &object) const
Less than method.
int getDay() const
day of the month [1-31]
tm * tp
representation
const tm * operator->() const
Smart pointer.
friend std::istream & operator>>(std::istream &in, JDateAndTime &object)
Read date and time from input stream.
float getFS() const
fraction of second
const JDateAndTime & operator()()
Set date and time.
tm * get() const
Get representation.
int getMonth() const
month of the year [1-12]
JDateAndTime(const time_t t1, const bool utc=false)
Constructor.
Definition: JDateAndTime.hh:98
static bool isISO8601(const std::string &buffer)
Function to check ISO-8601 conformity.
int getSeconds() const
seconds after the minute [0-59]
void set(const time_t t1, const bool utc=false)
Set to given time.
void sub(const time_t t1)
Subtract given time.
void add(const time_t t1)
Add given time.
float fs
fraction of second
void set(const time_t t1, const float f1, const bool utc=false)
Set to given time.