TimingUtilities.cpp
Go to the documentation of this file.
1 #include <NovaTimingUtilities/TimingUtilities.h>
2 #include <boost/date_time/posix_time/posix_time.hpp>
3 #include <cstdio>
4 
5 namespace BPT = boost::posix_time;
6 
7 namespace novadaq {
8 
9 namespace timeutils {
10 
11 /**
12  * Free function to convert UNIX system time (seconds and nanoseconds)
13  * to NOvA base time.
14  *
15  * @return true if the conversion worked, false if failed
16  */
17 bool convertUnixTimeToNovaTime(struct timespec const& inputUnixTime,
18  uint64_t& outputNovaTime)
19 {
20  if ((unsigned)inputUnixTime.tv_sec < NOVA_EPOCH) {return false;}
21 
22  long seconds=inputUnixTime.tv_sec;
23  // test in chrono order
24  if (seconds > 1341100799) // 23:59:59, Jun 30, 2012
25  ++seconds;
26  if (seconds > 1435708799) //23:59:59, Jun 30, 2015
27  {
28  ++seconds;
29  }
30 
31  if (seconds > 1483228799) //23:59:59, Dec 31, 2016
32  {
33  ++seconds;
34  }
35 
36  outputNovaTime =
37  ((uint64_t) (seconds - NOVA_EPOCH) * NOVA_TIME_FACTOR) +
38  (((uint64_t) inputUnixTime.tv_nsec * NOVA_TIME_FACTOR) / 1000000000);
39 
40  return true;
41 }
42 
43 /**
44  * Free function to convert UNIX system time (seconds and microseconds)
45  * to NOvA base time.
46  *
47  * @return true if the conversion worked, false if failed
48  */
49 bool convertUnixTimeToNovaTime(struct timeval const& inputUnixTime,
50  uint64_t& outputNovaTime)
51 {
52  if ((unsigned)inputUnixTime.tv_sec < NOVA_EPOCH) {return false;}
53 
54  // test in chrono order
55  time_t adjusted_seconds = inputUnixTime.tv_sec;
56  if (adjusted_seconds > 1341100799) // Jun 30 23:59:59 2012 UTC
57  { ++adjusted_seconds;
58  }
59  if (adjusted_seconds > 1435708799) // Jun 30 23:59:59 2015 UTC
60  { ++adjusted_seconds;
61  }
62 
63  if (adjusted_seconds > 1483228799) // Dec 31 23:59:59 2016 UTC
64  {
65  ++adjusted_seconds;
66  }
67 
68  outputNovaTime =
69  ((uint64_t) (adjusted_seconds - NOVA_EPOCH) * NOVA_TIME_FACTOR) +
70  (((uint64_t) inputUnixTime.tv_usec * NOVA_TIME_FACTOR) / 1000000);
71 
72  return true;
73 }
74 
75 /**
76  * Free function to convert UNIX system time as a tm struct in UTC
77  * to NOvA base time.
78  *
79  * @param inputUnixTime in a tm struct format (UTC)
80  * @param outputNovaTime - nova time in clock ticks relative to epoch
81  *
82  * @return true if conversion worked, false if failed
83  */
84 bool convertUnixTimeToNovaTime(struct tm inputUnixTime,
85  uint64_t& outputNovaTime)
86 {
87  time_t timeret = timegm(&inputUnixTime);
88  if ( timeret < 0 ) return false; // error occurred in timegm
89  timeval inputtimeval;
90  inputtimeval.tv_sec = timeret;
91  inputtimeval.tv_usec = 0;
92  return convertUnixTimeToNovaTime(inputtimeval,outputNovaTime);
93 
94 }
95 
96 /**
97  * Free function to convert UNIX system time (UTC) as a sec,min,hour,mday,mon,year
98  * to NOvA base time.
99  *
100  * The meaning of each input parameter is the same as that in the tm struct:
101  * @param sec - seconds after the minute (nominally 0-59, but up to 61 to allow for leap seconds)
102  * @param min - minutes after the hour (0-59)
103  * @param hour - hours since midnight (0-23)
104  * @param mday - day of the month (1-31)
105  * @param mon - months since January (0-11)
106  * @param year - years since 1900
107  *
108  * Output parameter:
109  * @param outputNovaTime - nova time in clock ticks relative to epoch
110  *
111  * @return true if success, else false.
112  */
113 bool convertUnixTimeToNovaTime(uint16_t sec, uint16_t min, uint16_t hour, uint16_t mday,
114  uint16_t mon, uint32_t year, uint64_t& outputNovaTime) {
115 
116  tm timeTM;
117  timeTM.tm_sec = sec;
118  timeTM.tm_min = min;
119  timeTM.tm_hour = hour;
120  timeTM.tm_mday = mday;
121  timeTM.tm_mon = mon;
122  timeTM.tm_year = year;
123  return convertUnixTimeToNovaTime(timeTM,outputNovaTime);
124 
125 }
126 
127 /**
128  * Free function to convert NOvA base time to UNIX system time
129  * (seconds and microseconds).
130  *
131  * @return true if the conversion worked, false if failed
132  */
133 bool convertNovaTimeToUnixTime(uint64_t const& inputNovaTime,
134  struct timeval& outputUnixTime)
135 {
136  double doubleTime = (double) inputNovaTime /
137  (double) NOVA_TIME_FACTOR;
138  time_t time_sec = (time_t) doubleTime;
139  outputUnixTime.tv_sec = NOVA_EPOCH + time_sec;
140  outputUnixTime.tv_usec = (suseconds_t)
141  ((doubleTime - (double)time_sec) * 1000000);
142  // test in chrono order
143  if (outputUnixTime.tv_sec > 1341100799) // Jun 30 23:59:59 2012 UTC
144  { --outputUnixTime.tv_sec;
145  }
146  if (outputUnixTime.tv_sec > 1435708799) // Jun 30 23:59:59 2015 UTC
147  { --outputUnixTime.tv_sec;
148  }
149 
150  if (outputUnixTime.tv_sec > 1483228799) // Dec 31 23:59:59 2016 UTC
151  {
152  --outputUnixTime.tv_sec;
153  }
154  return true;
155 }
156 
157 /**
158  * Free function to convert NOvA base time to UNIX system time
159  * (seconds and nanoseconds).
160  *
161  * @return true if the conversion worked, false if failed
162  */
163 bool convertNovaTimeToUnixTime(uint64_t const& inputNovaTime,
164  struct timespec& outputUnixTime)
165 {
166  double doubleTime = (double) inputNovaTime /
167  (double) NOVA_TIME_FACTOR;
168  time_t time_sec = (time_t) doubleTime;
169  outputUnixTime.tv_sec = NOVA_EPOCH + time_sec;
170  outputUnixTime.tv_nsec = (long)
171  (inputNovaTime - (time_sec*NOVA_TIME_FACTOR)) * 1000/64;
172  // test chronological (start with first nova experienced)
173  if (outputUnixTime.tv_sec > 1341100799) // Jun 30 23:59:59 2012 UTC
174  { --outputUnixTime.tv_sec;
175  }
176  if (outputUnixTime.tv_sec > 1435708799) // Jun 30 23:59:59 2015 UTC
177  { --outputUnixTime.tv_sec;
178  }
179 
180  if (outputUnixTime.tv_sec > 1483228799) // Dec 31 23:59:59 2016 UTC
181  {
182  --outputUnixTime.tv_sec;
183  }
184 
185  return true;
186 }
187 
188 /**
189  * Free function to convert NOvA base time to UNIX system time (UTC)
190  * expressed as a tm struct.
191  *
192  * @param inputNovaTime - nova time in clock ticks relative to epoch
193  * @param outputUnixTime in a tm struct format
194  *
195  * @return true if the conversion worked, else false.
196  */
197 bool convertNovaTimeToUnixTime(uint64_t const& inputNovaTime,
198  struct tm& outputUnixTime)
199 {
200  timeval outputTimeval;
201  if ( !convertNovaTimeToUnixTime(inputNovaTime,outputTimeval) ) return false;
202  outputUnixTime = *gmtime(&(outputTimeval.tv_sec));
203 
204  return true;
205 }
206 
207 /**
208  * Free function to convert NOvA base time to UNIX system time in (sec,min,hour,...) (UTC)
209  * Input parameter:
210  * @param inputNovaTime - nova time in clock ticks relative to nova epoch
211  * Output parameters:
212  * @param sec - seconds after the minute (nominally 0-59, but up to 61 to allow for leap seconds)
213  * @param min - minutes after the hour (0-59)
214  * @param hour - hours since midnight (0-23)
215  * @param mday - day of the month (1-31)
216  * @param mon - months since January (0-11)
217  * @param year - years since 1900
218  *
219  * @return true if the conversion worked, else false
220  */
221 bool convertNovaTimeToUnixTime(uint64_t const& inputNovaTime,
222  uint16_t& sec, uint16_t& min, uint16_t& hour, uint16_t& mday,
223  uint16_t& mon, uint32_t& year)
224 {
225 
226  tm outputTimeTM;
227  if ( !convertNovaTimeToUnixTime(inputNovaTime,outputTimeTM) ) return false;
228  sec = outputTimeTM.tm_sec;
229  min = outputTimeTM.tm_min;
230  hour = outputTimeTM.tm_hour;
231  mday = outputTimeTM.tm_mday;
232  mon = outputTimeTM.tm_mon;
233  year = outputTimeTM.tm_year;
234 
235  return true;
236 
237 }
238 
239 /**
240  * Free function to return the current time in units of the
241  * NOvA base clock.
242  *
243  * @return true if the fetching of the time worked, false if failed
244  */
245 bool getCurrentNovaTime(uint64_t& outputNovaTime)
246 {
247  struct timeval now;
248  if (gettimeofday(&now, 0) != 0) {
249  return false;
250  }
251  return convertUnixTimeToNovaTime(now, outputNovaTime);
252 }
253 
254 /**
255  * Free function to format a NOvA time as a datetime string.
256  */
257 std::string convertNovaTimeToString(uint64_t const& inputNovaTime)
258 {
259  // deal with whole seconds first
260  struct timespec unixTime;
261  convertNovaTimeToUnixTime(inputNovaTime, unixTime);
262  BPT::ptime posixTime = BPT::from_time_t(unixTime.tv_sec);
263  std::string workingString = BPT::to_simple_string(posixTime);
264 
265  // now fractional seconds
266  /*uint64_t wholePart = ((uint64_t) unixTime.tv_sec - NOVA_EPOCH) *
267  NOVA_TIME_FACTOR;*/
268  uint64_t wholePart = (inputNovaTime/NOVA_TIME_FACTOR) * NOVA_TIME_FACTOR; // classic integer math
269  uint64_t fractionalPart = inputNovaTime - wholePart;
270  uint64_t picoSeconds = (uint64_t) (1E12 * fractionalPart / NOVA_TIME_FACTOR);
271  char fractionalString[20];
272  sprintf(fractionalString, "%012llu", (unsigned long long)picoSeconds);
273  workingString.append(".");
274  workingString.append(fractionalString);
275  workingString.append(" UTC");
276 
277  return workingString;
278 }
279 
280 /**
281  * Free function to format a UNIX timespec as a datetime string.
282  */
283 std::string convertUnixTimeToString(struct timespec const& inputUnixTime)
284 {
285  // deal with whole seconds first
286  BPT::ptime posixTime = BPT::from_time_t(inputUnixTime.tv_sec);
287  std::string workingString = BPT::to_simple_string(posixTime);
288 
289  // now fractional seconds
290  char fractionalString[20];
291  sprintf(fractionalString, "%09ld", inputUnixTime.tv_nsec);
292  workingString.append(".");
293  workingString.append(fractionalString);
294  workingString.append(" UTC");
295 
296  return workingString;
297 }
298 
299 /**
300  * Free function to format a UNIX timeval as a datetime string.
301  */
302 std::string convertUnixTimeToString(struct timeval const& inputUnixTime)
303 {
304  // deal with whole seconds first
305  BPT::ptime posixTime = BPT::from_time_t(inputUnixTime.tv_sec);
306  std::string workingString = BPT::to_simple_string(posixTime);
307 
308  // now fractional seconds
309  char fractionalString[20];
310  sprintf(fractionalString, "%06ld", inputUnixTime.tv_usec);
311  workingString.append(".");
312  workingString.append(fractionalString);
313  workingString.append(" UTC");
314 
315  return workingString;
316 }
317 
318 /* Subtract two timevals, return 0 if positive, 1 if negative */
319 /* Stolen from:
320  http://www.gnu.org/s/libc/manual/html_node/Elapsed-Time.html */
321 
322 int timeval_subtract (struct timeval* result, struct timeval* xx,
323  struct timeval* yy)
324 {
325  // isolate the input varibles: we don't want our carrying later
326  // to modify the things being compared. We only want to
327  // modify the result. So, create copies to work with.
328  struct timeval *x = new struct timeval;
329  struct timeval *y = new struct timeval;
330  x->tv_sec = xx->tv_sec; x->tv_usec = xx->tv_usec;
331  y->tv_sec = yy->tv_sec; y->tv_usec = yy->tv_usec;
332 
333  /* Perform the carry for the later subtraction by updating y. */
334  if (x->tv_usec < y->tv_usec) {
335  int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
336  y->tv_usec -= 1000000 * nsec;
337  y->tv_sec += nsec;
338  }
339  if (x->tv_usec - y->tv_usec > 1000000) {
340  int nsec = (x->tv_usec - y->tv_usec) / 1000000;
341  y->tv_usec += 1000000 * nsec;
342  y->tv_sec -= nsec;
343  }
344 
345  /* Compute the time remaining to wait.
346  tv_usec is certainly positive. */
347  result->tv_sec = x->tv_sec - y->tv_sec;
348  result->tv_usec = x->tv_usec - y->tv_usec;
349 
350  /* Return 1 if result is negative. */
351  return x->tv_sec < y->tv_sec;
352 }
353 
354 } // end of namespace timeutils
355 
356 } // end of namespace novadaq
const uint32_t NOVA_EPOCH
Double_t xx
Definition: macro.C:12
const uint64_t NOVA_TIME_FACTOR
bool convertNovaTimeToUnixTime(uint64_t const &inputNovaTime, struct timespec &outputUnixTime)
bool getCurrentNovaTime(uint64_t &outputNovaTime)
std::string convertNovaTimeToString(uint64_t const &inputNovaTime)
int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
static float min(const float a, const float b, const float c)
Definition: absgeo.cxx:45
std::string convertUnixTimeToString(struct timespec const &inputNovaTime)
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
bool convertUnixTimeToNovaTime(struct timespec const &inputUnixTime, uint64_t &outputNovaTime)
static constexpr Double_t year
Definition: Munits.h:185