source: trunk/FACT++/src/Time.cc@ 13717

Last change on this file since 13717 was 12618, checked in by tbretz, 13 years ago
Implemented Time::UnixDate and use this instead of UnixTime when writing TSTART and TSTOP in FITS header -- units there are days not seconds.
File size: 9.7 KB
Line 
1// **************************************************************************
2/** @class Time
3
4@brief Adds some functionality to boost::posix_time::ptime for our needs
5
6This is basically a wrapper around boost::posix_time::ptime which is made
7to adapt the functionality to our needs. Time can store the current
8data and time with a precision up to nanoseconds if provided by the
9undrlaying system, otherwise microsecond precision is used.
10
11It main purpose is to provide needed constructors and simplyfy the
12conversion of dates and times from and to a string/stream.
13
14Note that posix_time (as Posix times have) has a limited range. You cannot
15use it for example for very early years of the last century.
16
17@section Examples
18
19 - An example can be found in \ref time.cc
20
21@section References
22
23 - <A HREF="http://www.boost.org/doc/libs/1_45_0/doc/html/date_time.html">BOOST++ date_time (V1.45.0)</A>
24
25**/
26// **************************************************************************
27#include "Time.h"
28
29using namespace std;
30using namespace boost::posix_time;
31
32const boost::gregorian::date Time::fUnixOffset(1970, 1, 1);
33
34const Time Time::None(Time::none);
35
36// strftime
37const _time_format Time::reset = 0;
38const _time_format Time::def = "%c";
39const _time_format Time::std = "%x %X%F";
40const _time_format Time::sql = "%Y-%m-%d %H:%M:%S.%f";
41const _time_format Time::ssql = "%Y-%m-%d %H:%M:%S";
42const _time_format Time::iso = "%Y%m%dT%H%M%S%F%q";
43const _time_format Time::magic = "%Y %m %d %H %M %S %f";
44const _time_format Time::smagic = "%Y %m %d %H %M %S";
45
46// --------------------------------------------------------------------------
47//
48//! Construct a Time object with either UTC or local time, or without any
49//! particular time.
50//!
51//! @param typ
52//! enum as defined in Time::init_t
53//
54Time::Time(enum init_t typ)
55{
56 switch (typ)
57 {
58 case utc:
59 *this = microsec_clock::universal_time();
60 break;
61 case local:
62 *this = microsec_clock::local_time();
63 break;
64 case none:
65 break;
66 }
67}
68
69
70// --------------------------------------------------------------------------
71//
72//! Construct a Time object with a date_time::special_value, e.g.
73//!
74//! - neg_infin
75//! - pos_infin
76//! - not_a_date_time
77//! - max_date_time
78//! - min_date_time
79//!
80//!
81//! @param val
82//! date_time::special_value
83//
84Time::Time(const boost::date_time::special_values &val) : ptime(val)
85{
86}
87
88// --------------------------------------------------------------------------
89//
90//! Construct a Time object from seconds since 1970/1/1 and number of
91//! milliseconds, as for example returned by gettimeofday()
92//!
93//! @param tm
94//! seconds since 1970/1/1
95//!
96//! @param millisec
97//! number of milliseconds
98//
99Time::Time(const time_t &tm, const int &millisec)
100: ptime(fUnixOffset, time_duration(0, 0, tm, millisec))
101{
102}
103
104// --------------------------------------------------------------------------
105//
106//! Construct a Time from a date and time.
107//!
108//! @param year, month, day, hh, mm, ss, microsec
109//! A full date and time down to microsecond precision. From the end
110//! arguments can be omitted.
111//!
112Time::Time(short year, unsigned char month, unsigned char day,
113 unsigned char hh, unsigned char mm, unsigned char ss, unsigned int microsec)
114// Last argument is fractional_seconds ( correct with num_fractional_digits() )
115: ptime(boost::gregorian::date(year, month, day),
116 time_duration(hh, mm, ss, microsec*pow(10, time_of_day().num_fractional_digits()-6)))
117{
118}
119
120// --------------------------------------------------------------------------
121//
122//! Set the Time object to a given MJD. Note that this involves
123//! conversion from double. So converting forth and back many many
124//! times might results in drifts.
125//!
126//! @param mjd
127//! Modified Julian Date
128//!
129void Time::Mjd(double mjd)
130{
131 // Convert MJD to seconds since offset
132 mjd -= 40587;
133 mjd *= 24*60*60;
134
135 const int exp = time_of_day().num_fractional_digits();
136 const double frac = fmod(mjd, 1)*pow(10, exp);
137
138 *this = ptime(fUnixOffset, time_duration(0, 0, mjd, frac));
139}
140
141// --------------------------------------------------------------------------
142//
143//! @returns the seconds of the day including the fractional seconds.
144//!
145double Time::SecondsOfDay() const
146{
147 const time_duration tod = time_of_day();
148
149 const int exp = tod.num_fractional_digits();
150
151 const double frac = tod.fractional_seconds()/pow(10, exp);
152 const double sec = tod.total_seconds()+frac;
153
154 return sec;
155}
156
157// --------------------------------------------------------------------------
158//
159//! Get the current MJD. Note that this involves
160//! conversion to double. So converting forth and back many many
161//! times might results in drifts.
162//!
163//! @returns
164//! Modified Julian Date
165//!
166double Time::Mjd() const
167{
168 return date().modjulian_day()+SecondsOfDay()/(24*60*60);
169
170 /*
171 const time_duration mjd = *this - ptime(fUnixOffset);
172 const double sec = mjd.total_seconds()+mjd.fractional_seconds()/1e6;
173 return sec/(24*60*60)+40587;
174 */
175}
176
177// --------------------------------------------------------------------------
178//
179// @returns seconds since 1970/1/1
180//
181double Time::UnixTime() const
182{
183 return (date().modjulian_day()-40587)*24*60*60 + SecondsOfDay();
184}
185
186// --------------------------------------------------------------------------
187//
188// @returns days since 1970/1/1
189//
190double Time::UnixDate() const
191{
192 return (date().modjulian_day()-40587) + SecondsOfDay()/(24*60*60);
193}
194
195// --------------------------------------------------------------------------
196//
197// @returns seconds since 1970/1/1
198//
199time_t Time::Time_t() const
200{
201 return (date().modjulian_day()-40587)*24*60*60 + time_of_day().total_seconds();
202}
203
204// --------------------------------------------------------------------------
205//
206//! @returns the time in a format needed for root's TAxis
207//!
208double Time::RootTime() const
209{
210 return (date().modjulian_day()-49718)*24*60*60 + SecondsOfDay();
211}
212
213// --------------------------------------------------------------------------
214//
215//! Returns a string with the contents of the Time object formated
216//! as defined in format.
217//!
218//! @param format
219//! format description of the string to be returned. For details
220//! see the boost documentation or the man page of strftime
221//!
222//! @returns
223//! A string with the time formatted as requested. Note some special
224//! strings might be returned in case the time is invalid.
225//
226string Time::GetAsStr(const char *format) const
227{
228 stringstream out;
229 out << Time::fmt(format) << *this;
230 return out.str();
231}
232
233// --------------------------------------------------------------------------
234//
235//! @returns
236//! a human readable string which complies with ISO 8601, in the
237//! "CCYY-MM-DDThh:mm:ss.f"
238//
239string Time::Iso() const
240{
241 stringstream out;
242 out << Time::fmt("%Y-%m-%dT%H:%M:%S%F") << *this;
243 return out.str();
244}
245
246// --------------------------------------------------------------------------
247//
248//! Sets the time of the Time object to a time corresponding to
249//! the one given as argument. It is evaluated according to the given
250//! format.
251//!
252//! @param str
253//! The time as a string which should be converted to the Time object
254//!
255//! @param format
256//! format description of the string to be returned. For details
257//! see the boost documentation or the man page of strftime
258//!
259void Time::SetFromStr(const string &str, const char *format)
260{
261 // FIXME: exception handline
262 stringstream stream;
263 stream << str;
264 stream >> Time::fmt(format) >> *this;
265}
266
267// --------------------------------------------------------------------------
268//
269//! @returns
270//! an int corresponding to the stored time minus 12 hours of the form
271//! YYYYMMDD, e.g. 20111224 for Christmas eve 2011
272//
273int Time::NightAsInt() const
274{
275 const Time tm = *this - boost::posix_time::hours(12);
276 return tm.Y()*10000 + tm.M()*100 + tm.D();
277}
278
279// --------------------------------------------------------------------------
280//
281//! A stream manipulator which sets the streams Time output format
282//! as defined in the argument.
283//!
284//! @param format
285//! format description of the manipulator be returned. For details
286//! see the boost documentation or the man page of strftime
287//!
288//! @returns
289//! a stream manipulator for the given format
290//!
291const _time_format Time::fmt(const char *format)
292{
293 return format;
294}
295
296// --------------------------------------------------------------------------
297//
298//! Sets the locale discription of the stream (the way how a time is
299//! output) to the format defined by the given manipulator.
300//!
301//! Example:
302//! \code
303//! Time t();
304//! cout << Time::fmt("%Y:%m:%d %H:%M:%S.%f") << t << endl;
305//! \endcode
306//!
307//! @param out
308//! Reference to the stream
309//!
310//! @param f
311//! Time format described by a manipulator
312//!
313//! @returns
314//! A reference to the stream
315//!
316ostream &operator<<(ostream &out, const _time_format &f)
317{
318 const locale loc(locale::classic(),
319 f.ptr==0 ? 0 : new time_facet(f.ptr));
320
321 out.imbue(loc);
322
323 return out;
324}
325
326// --------------------------------------------------------------------------
327//
328//! Sets the locale discription of the stream (the way how a time is
329//! input) to the format defined by the given manipulator.
330//!
331//! Example:
332//! \code
333//! stringstream s;
334//! s << "09.09.1974 21:59";
335//!
336//! Time t;
337//! s >> Time::fmt("%d.%m.%Y %H:%M") >> t;
338//! \endcode
339//!
340//! @param in
341//! Reference to the stream
342//!
343//! @param f
344//! Time format described by a manipulator
345//!
346//! @returns
347//! A reference to the stream
348//!
349istream &operator>>(istream &in, const _time_format &f)
350{
351 const locale loc(locale::classic(),
352 f.ptr==0 ? 0 : new time_input_facet(f.ptr));
353
354 in.imbue(loc);
355
356 return in;
357}
358
Note: See TracBrowser for help on using the repository browser.