FARGOS/VISTA Object Management Environment Core  ..
FARGOS/VISTA Object Management Environment Core Table of Contents
time_point.hpp
Go to the documentation of this file.
1 #ifndef _TIME_POINT_HPP_
2 #define _TIME_POINT_HPP_ "$Id: time_point.hpp 456 2020-07-23 20:25:49Z geoff $"
4 
6 /* Copyright (C) 2010 - 2019 FARGOS Development, LLC */
7 
9 #include <utils/base/text2int.h>
11 #include <utils/time/tick_time.h>
12 #include <utils/time/get_time.h>
13 #include <iostream>
14 #include <stdio.h>
15 #include <time.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <map>
19 
50 #ifdef _WIN32
51 #define CALL_TZSET() if (TimePointCache::TimePoint_setTZ == false) TimePointCache::doSetTZ()
52 #else
53 #define CALL_TZSET() do { } while (0) /* null statement */
54 #endif
55 
56 template <unsigned int UNITS> extern CONSTEXPR unsigned int int_digitsNeeded() OME_CONST_FUNCTION OME_ALWAYS_INLINE;
57 
61 template <unsigned int UNITS> inline CONSTEXPR unsigned int int_digitsNeeded()
62 {
63  return (1 + int_digitsNeeded<UNITS / 10>());
64 }
65 
67 template <> inline CONSTEXPR unsigned int int_digitsNeeded<1>()
68 {
69  return (0);
70 }
71 
73 template <> inline CONSTEXPR unsigned int int_digitsNeeded<0>()
74 {
75  return (0);
76 }
77 
93 public:
94 #ifdef _WIN32
95  static bool TimePoint_setTZ;
96 
98  static void doSetTZ();
99 #endif
100  struct tm localMidnight;
101  struct tm localEndOfDay;
102  struct tm local3am; // sufficiently skewed to avoid any DST issues
103  struct tm lastTime;
104  struct tm utc3am;
110 
111  // not needed ~TimePointCache() {}
112 
115  localEndOfDayEpoch = 0; // force isForDay() to be false
116  }
117 
124  explicit TimePointCache(const time_t asOfPOSIXepoch)
125  {
126  localEndOfDayEpoch = 0; // force isForDay() to be false
127  initializeForDay(asOfPOSIXepoch);
128  }
129 
138  explicit TimePointCache(const struct timespec &asIfOnDay)
139  {
140  initializeForDay(asIfOnDay);
141  }
142 
146  explicit TimePointCache(const struct tm &asIfOnDay)
147  {
148  initializeForDay(asIfOnDay);
149  }
150 
154  void initializeForDay(const struct tm &asIfOnDay)
155  {
156  lastTime = asIfOnDay;
157  localMidnight = asIfOnDay;
158  localMidnight.tm_sec = 0;
159  localMidnight.tm_min = 0;
160  localMidnight.tm_hour = 0;
161  localMidnight.tm_isdst = -1; // unknown
163  localEndOfDay.tm_hour = 24;
165  local3am.tm_hour = 3;
166 
169  local3amEpoch = mktime(&local3am);
170  lastTimeEpoch = mktime(&lastTime);
171  // convert our 3am time to UTC
172 #ifdef _WIN32
173  gmtime_s(&utc3am, &local3amEpoch);
174 #else
175  gmtime_r(&local3amEpoch, &utc3am);
176 #endif
177  // use standard semantics of zones like Eastern being negative
178  utcDifferenceSeconds = (local3am.tm_hour - utc3am.tm_hour) * (60 * 60);
179  // TODO: handle fractional zone if such a deployment scenario arises
180  }
181 
189  void initializeForDay(const struct timespec &asIfOnDay)
190  {
191  struct tm expandedFields;
192 #ifdef _WIN32
193  CALL_TZSET();
194  localtime_s(&expandedFields, &(asIfOnDay.tv_sec));
195 #else
196  localtime_r(&(asIfOnDay.tv_sec), &expandedFields);
197 #endif
198  initializeForDay(expandedFields);
199  }
200 
201  bool isForDay(const time_t t) const OME_ALWAYS_INLINE {
202  /* NOTE: localEndOfDayEpoch == 0 is used to force
203  * this to return false. In practice, most times
204  * will be before the end-of-day, so we check it last.
205  */
206  if ((t >= localMidnightEpoch) && (t < localEndOfDayEpoch)) {
207  return (true);
208  }
209  return (false);
210  }
211 
223  void initializeForDay(const time_t asOfPOSIXepoch)
224  {
225  if (isForDay(asOfPOSIXepoch) == true) {
226  return; // assume already initialized
227  }
228  struct timespec todayTime;
229  if (asOfPOSIXepoch == 0) { // was not set...
230  // These objects should be infrequently created, so we force
231  // a kernel call to retrieve the time and thus avoid any dependency
232  // on having the clock rate determined prior to this call.
233  clock_gettime_via_tick(&todayTime, true);
234  } else {
235  todayTime.tv_sec = asOfPOSIXepoch;
236  todayTime.tv_nsec = 0;
237  }
238  initializeForDay(todayTime);
239  }
240 
242  return (utcDifferenceSeconds);
243  }
244 
245  bool isForDay(const struct tm &dayOfInterest) const {
246  if ((local3am.tm_mday == dayOfInterest.tm_mday) &&
247  (local3am.tm_mon == dayOfInterest.tm_mon) &&
248  (local3am.tm_year == dayOfInterest.tm_year) ) {
249  return (true);
250  }
251  return (false);
252  }
253 
254 }; // end class TimePointCache
255 
258 
270 private:
272  std::map<time_t,TimePointCache *> timeTable;
273 public:
274  explicit TimePointCacheTable(const char *tableName="timeCache") :
275  tblLock(tableName, (SharedMemoryVariableManager *) nullptr) // never allocate statistics for this
276  {}
277 
279 
292  const TimePointCache &getCacheEntry(time_t t) {
293  tblLock.LOCK_HERE();
294  std::map<time_t,TimePointCache *>::const_iterator i = timeTable.find(t);
295  if (i != timeTable.end()) {
296  const TimePointCache *result = i->second;
297  tblLock.unlock();
298  return (*result);
299  }
300  TimePointCache *newEntry = new TimePointCache(t);
301  timeTable[t] = newEntry; // save
302  tblLock.unlock();
303  return (*newEntry);
304  }
305 }; // end class TimePointCacheTable
306 
313 template <unsigned int UNITS> class POSIXtimeInUnits {
314 protected:
315  uint64_t time_in_units;
316 
318  const int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3") {
319  enum { one_billion = 1000000000UL }; // for readability
320 #ifdef _MSC_VER
321 #pragma warning(suppress : 4127)
322 #endif
323  if (UNITS == one_billion) { // test done at compile time
324  time_in_units = (time_ns.time_sec * UNITS) + time_ns.time_nanosec +
325  (static_cast<int64_t>(skewByMinutes) * (static_cast<int64_t>(60) * UNITS));
326  } else {
327  enum { NS_PER_UNIT = one_billion / UNITS }; // compile-time constant
328  int64_t fractionalUnits;
329  if (time_ns.time_nanosec < NS_PER_UNIT) { // avoid the division if we can
330  fractionalUnits = 0;
331  } else {
332  fractionalUnits = time_ns.time_nanosec / NS_PER_UNIT;
333  }
334  uint64_t totalSeconds = time_ns.time_sec + (skewByMinutes * 60);
335  time_in_units = (totalSeconds * UNITS) + fractionalUnits;
336  }
337  }
338 
339 public:
340  /* NOTE: functions are defined before they are used to ensure
341  * they can be inlined.
342  */
343 
351  inline uint64_t convertToCustomEpochUnits(uint64_t desired_granularity=UNITS) const OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3") {
352 #ifdef _MSC_VER
353 #pragma warning(suppress : 4127)
354 #endif
355  if (desired_granularity == UNITS) { // test done at compile-time
356  return (time_in_units);
357  }
358  if (desired_granularity > UNITS) { // test done at compile time
359  /* NOTE: assuming desired_granularity is a constant, then
360  * if conversion is possible by via a simple integer
361  * multiplication, the resulting code will be comprised of just
362  * a multiplication by a constant; otherwise this code block
363  * disappears entirely.
364  */
365  const uint64_t intRatio = desired_granularity / UNITS; // computed at compile time
366  if ((desired_granularity - (UNITS * intRatio)) == 0) { // test done at compile time
367  return (time_in_units * intRatio);
368  }
369  } else { // intend to decrease precision
370  /* NOTE: assuming desired_granularity is a constant and
371  * the intent was to decrease the resolution by an integral
372  * divisor, the code emitted will be comprised of just the
373  * steps needed to do that logical division by an integer
374  * constant. An actual division operation may not be
375  * emitted when the compiler knows of special sequences of
376  * shifts, adds and multiplies that yield the intended
377  * value without the need for an expensive division (which
378  * can be 20-100 times slower).
379  */
380  const uint64_t intRatio = UNITS / desired_granularity; // computed at compile time
381  if ((UNITS - (desired_granularity * intRatio)) == 0) { // test done at compile time
382  return (time_in_units / intRatio);
383  }
384  }
385  /* This code will be emitted only when needed to handle arbitrary
386  * or unknown-at-compile-time ratios.
387  * It avoids overflow by extracting the number of seconds and then
388  * converting the remaining fractional portion.
389  */
390  uint64_t secs = time_in_units / UNITS;
391  uint64_t fraction = time_in_units - (secs * UNITS);
392  uint64_t result = (secs * desired_granularity);
393  if (fraction != 0) { // only bother with conversion if needed
394  // now split out seconds and fractional units
395  uint64_t new_fraction = (fraction * desired_granularity) / UNITS;
396  result += new_fraction;
397  }
398  return (result);
399  }
400 
401 
402  /* NOTE: this class intentionally has no destructor nor copy constructor.
403  *
404  * This is crucial for performance so that the values can be passed in
405  * registers with no intervening code being invoked.
406  *
407  * Tempting as it may be to implement a templated assignment operator
408  * to permit conversions from different unit of granularity,
409  * this must be avoided.
410  *
411  * The workaround is to provide a templated cast operator.
412  */
413 
425  POSIXtimeInUnits(time_t seconds, int64_t fractional, int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3") {
426  /* most common usage is to pass seconds as 0
427  * and fractional as total nanoseconds. When inlined,
428  * skewByMinutes * 60 becomes 0, the add of 0 seconds is still 0,
429  * and 0 * UNITS is 0, resulting in secondsAsUnits being 0.
430  * Adding 0 to fractional allows this to reduce to just an assignment.
431  */
432  uint64_t secondsAsUnits = (static_cast<uint64_t>(seconds) + (skewByMinutes * 60)) * UNITS;
433  time_in_units = fractional + secondsAsUnits;
434  }
435 
444  explicit POSIXtimeInUnits(const TimeWithNanoseconds time_ns, int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3") {
445  assignFromTimeWithNanoseconds(time_ns, skewByMinutes);
446  }
447 
448 
451  template <unsigned int ALT_UNITS> operator POSIXtimeInUnits<ALT_UNITS>() const OME_ALWAYS_INLINE;
452 
453 #if 0
454  // specialization for when target units matches implementation
455  inline operator POSIXtimeInUnits<UNITS>() const OME_ALWAYS_INLINE {
456  return (*this);
457  }
458 #endif
459 
465  assignFromTimeWithNanoseconds(time_ns, 0);
466  return (*this);
467  }
468 
472  enum { one_billion = 1000000000UL }; // for readability
473 #ifdef _MSC_VER
474 #pragma warning(suppress : 4127)
475 #endif
476  if (UNITS == one_billion) { // test done at compile time
477  return (time_in_units);
478  }
479  uint64_t secs = time_in_units / UNITS;
480  uint64_t fraction = time_in_units - (secs * UNITS);
481  // now split out seconds and fractional units
482  uint64_t new_fraction = (fraction * one_billion) / UNITS;
483  uint64_t result = (secs * one_billion) + new_fraction;
484  return (result);
485  }
486 
489  inline time_t getSeconds() const OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3") {
490  uint64_t seconds = time_in_units / UNITS;
491  return (static_cast<time_t>(seconds));
492  }
493 
499  template <unsigned int ALT_UNITS> bool operator==(const POSIXtimeInUnits<ALT_UNITS> arg) const {
500  return ((ALT_UNITS == UNITS) ? (time_in_units == arg.time_in_units) :
501  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) == arg.time_in_units) :
502  (time_in_units == (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
503  }
504 
510  template <unsigned int ALT_UNITS> bool operator!=(const POSIXtimeInUnits<ALT_UNITS> arg) const {
511  return ((ALT_UNITS == UNITS) ? (time_in_units != arg.time_in_units) :
512  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) != arg.time_in_units) :
513  (time_in_units != (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
514  }
515 
521  template <unsigned int ALT_UNITS> bool operator<=(const POSIXtimeInUnits<ALT_UNITS> arg) const {
522  return ((ALT_UNITS == UNITS) ? (time_in_units <= arg.time_in_units) :
523  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) <= arg.time_in_units) :
524  (time_in_units <= (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
525  }
526 
532  template <unsigned int ALT_UNITS> bool operator>=(const POSIXtimeInUnits<ALT_UNITS> arg) const {
533  return ((ALT_UNITS == UNITS) ? (time_in_units >= arg.time_in_units) :
534  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) >= arg.time_in_units) :
535  (time_in_units >= (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
536  }
537 
543  template <unsigned int ALT_UNITS> bool operator<(const POSIXtimeInUnits<ALT_UNITS> arg) const {
544  return ((ALT_UNITS == UNITS) ? (time_in_units < arg.time_in_units) :
545  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) < arg.time_in_units) :
546  (time_in_units < (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
547  }
548 
554  template <unsigned int ALT_UNITS> bool operator>(const POSIXtimeInUnits<ALT_UNITS> arg) const {
555  return ((ALT_UNITS == UNITS) ? (time_in_units > arg.time_in_units) :
556  (UNITS < ALT_UNITS) ? ((powerOf10Constant<ALT_UNITS - UNITS>() * time_in_units) > arg.time_in_units) :
557  (time_in_units > (powerOf10Constant<UNITS - ALT_UNITS>() * arg.time_in_units)));
558  }
559 
565  TimeWithNanoseconds curTime;
566 
567  getCurrentTime(&curTime, false);
568  return (POSIXtimeInUnits<UNITS>(curTime));
569  }
570 }; // end class POSIXtimeInUnits<>
571 
572 
573 template <unsigned int UNITS> template<unsigned int ALT_UNITS> inline POSIXtimeInUnits<UNITS>::operator POSIXtimeInUnits<ALT_UNITS>() const
574 {
575  return POSIXtimeInUnits<ALT_UNITS>((int64_t) 0, this->convertToCustomEpochUnits(ALT_UNITS));
576 }
577 
581 
588 
596 template <unsigned int UNITS> class TimePointOfGranularity {
597 public:
598  enum {
599  OUTPUT_DATE=1, // corresponds to LOG_DATESTAMP
600  OUTPUT_TIME=2 // corresponds to LOG_TIMESTAMP
601  };
602  struct tm expandedTime;
603  uint64_t fractionalUnits;
604 
605  // utility routines are defined before they are used
606  // to ensure inlining is possible
607 
622  void initializeWithUnitsFromEpoch(time_t secondsSinceEpoch,
623  uint64_t fractionInUnits, int skewByMinutes=0,
624  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
625  {
626  uint64_t extraSeconds, fraction;
627  // only pay cost of division if needed...
628  if (fractionInUnits < UNITS) {
629  extraSeconds = 0;
630  fraction = fractionInUnits;
631  } else {
632  extraSeconds = fractionInUnits / UNITS;
633  fraction = fractionInUnits - (extraSeconds * UNITS);
634  }
635  time_t skewedTime = secondsSinceEpoch + extraSeconds + (skewByMinutes * 60);
636  // if between 3am and midnight, hours move monotonically
637  if ((cachedTimeInfo != nullptr) &&
638  (skewedTime >= cachedTimeInfo->local3amEpoch) &&
639  (skewedTime < cachedTimeInfo->localEndOfDayEpoch)) {
640  // start with 3am time
641  expandedTime = cachedTimeInfo->local3am;
642  time_t total_seconds = skewedTime - cachedTimeInfo->local3amEpoch;
643  time_t hours = total_seconds / (60 * 60); // 60 secs/min, 60 min/hour
644  time_t totalMinSecs = total_seconds - (hours * (60 * 60));
645  time_t mins = totalMinSecs / 60;
646  time_t secs = totalMinSecs - (mins * 60);
647 /* Generic code:
648  expandedTime->tm_hour += hours;
649  expandedTime->tm_min += mins;
650  expandedTime->tm_secs += secs;
651 */
652  expandedTime.tm_hour = hours + 3; // specific for 03:00:00 offset
653  expandedTime.tm_min = mins;
654  expandedTime.tm_sec = secs;
655  } else { // not in our cached window, do the heavy work to expand
656 #ifdef _WIN32
657  CALL_TZSET();
658  localtime_s(&expandedTime, &skewedTime);
659 #else
660  localtime_r(&skewedTime, &expandedTime);
661 #endif
662  }
663  fractionalUnits = fraction;
664  }
665 
681  inline void initializeWithNanosecondsFromEpoch(uint64_t nanosecondsSinceEpoch,
682  time_t secondsSinceEpoch=0,
683  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday,
684  int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
685  {
686  enum { one_billion = 1000000000UL }; // for readability
687 
688  // NOTE: this test is evaluated at compile-time
689 #ifdef _MSC_VER
690 #pragma warning(suppress : 4127)
691 #endif
692  if (UNITS == one_billion) { // avoid work if possible...
693  initializeWithUnitsFromEpoch(secondsSinceEpoch,
694  nanosecondsSinceEpoch, skewByMinutes, cachedTimeInfo);
695  } else {
696  enum { NS_PER_UNIT = one_billion / UNITS }; // compile-time constant
697  uint64_t extraSeconds, nanoseconds;
698  // only pay cost of division if needed...
699  if (nanosecondsSinceEpoch < one_billion) {
700  extraSeconds = 0;
701  nanoseconds = nanosecondsSinceEpoch;
702  } else {
703  extraSeconds = nanosecondsSinceEpoch / one_billion;
704  nanoseconds = nanosecondsSinceEpoch - (extraSeconds * one_billion);
705  }
706  time_t totalSeconds = secondsSinceEpoch + extraSeconds;
707 
708  uint64_t unit_fraction = nanoseconds / NS_PER_UNIT;
709  initializeWithUnitsFromEpoch(totalSeconds, unit_fraction,
710  skewByMinutes, cachedTimeInfo);
711  }
712  }
713 
714 
717 
724  explicit TimePointOfGranularity(const struct tm &explodedTime, uint64_t fraction=0)
725  {
726  expandedTime = explodedTime;
727  fractionalUnits = fraction;
728  }
729 
740  template <unsigned int PT_UNITS>
742  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday,
743  int skewByMinutes=0)
744  {
745  // NOTE: when UNITS == PT_UNITS, this just a copies a uint64_t
746  uint64_t fract = ptTime.convertToCustomEpochUnits(UNITS);
747  // NOTE: "this->" usage needed since this is a template
748  this->initializeWithUnitsFromEpoch(0, fract, skewByMinutes, cachedTimeInfo);
749  }
750 
751 #if 0 // a non-default copy constructor creates unwanted overhead
754  {
757  }
758 #endif
759 
768  explicit TimePointOfGranularity(const char *dayAndTime,
769  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) {
770  convertDayAndTime(dayAndTime, cachedTimeInfo);
771  }
772 
781  TimePointOfGranularity(const char *day, const char *timeOfDay,
782  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) {
783  convertDayAndTime(day, timeOfDay, cachedTimeInfo);
784  }
785 
799  explicit TimePointOfGranularity(time_t secondsSinceEpoch,
800  uint64_t fraction=0, int skewByMinutes=0,
801  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
802  {
803  initializeWithUnitsFromEpoch(secondsSinceEpoch, fraction,
804  skewByMinutes, cachedTimeInfo);
805  }
806 
807 
809  template <unsigned int INCOMING_UNITS=UNITS> TimePointOfGranularity<UNITS> &operator=(const TimePointOfGranularity<INCOMING_UNITS> &arg) {
811 #ifdef _MSC_VER
812 #pragma warning(suppress : 4127)
813 #endif
814  if (INCOMING_UNITS == UNITS) { // NOTE: evaluated at compile time
816  } else {
817 #ifdef _MSC_VER
818 #pragma warning(suppress : 4127)
819 #endif
820  if (UNITS >= INCOMING_UNITS) { // evaluated at compile time
821  // scale up
822  fractionalUnits = arg.fractionalUnits * powerOf10Constant<UNITS - INCOMING_UNITS>();
823  } else { // reduce resolution
824  fractionalUnits = arg.fractionalUnits / powerOf10Constant<INCOMING_UNITS - UNITS>();
825  }
826  }
827  return (*this);
828  }
829 
831  TimePointOfGranularity<UNITS> &operator=(const struct tm &POSIXexpandedDate) {
832  expandedTime = POSIXexpandedDate;
833  fractionalUnits = 0;
834  return (*this);
835  }
836 
839  explicit operator const struct tm &() const OME_ALWAYS_INLINE {
840  return (expandedTime);
841  }
842 
850  enum { one_billion = 1000000000UL }; // for readability
851  // if cached info provided and for exact same day and after 3am
852  if ((cachedTimeInfo != nullptr) &&
853  (expandedTime.tm_mday == cachedTimeInfo->local3am.tm_mday) &&
854  (expandedTime.tm_mon == cachedTimeInfo->local3am.tm_mon) &&
855  (expandedTime.tm_year == cachedTimeInfo->local3am.tm_year) &&
856  (expandedTime.tm_hour >= 3)) { // 3 = 3am
857  // NOTE: for performance, we use the true constant values as
858  // there's no need to read them from memory and the subtract zero
859  // operations just collapse to logical assignments.
860  // Implied field documented in comment to right.
861  int hours = expandedTime.tm_hour - 3; // cachedTimedInfo->local3am.tv_hour;
862  int mins = expandedTime.tm_min - 0; // cachedTimedInfo->local3am.tv_min;
863  int secs = expandedTime.tm_sec - 0; // cachedTimedInfo->local3am.tv_sec;
864 #if 0 // By definition, 03:00:00 AM can't have these cases
865  if (secs < 0) {
866  secs += 60;
867  mins -= 1;
868  }
869  if (mins < 0) {
870  hours -= 1;
871  mins += 60;
872  }
873 #endif
874  uint64_t seconds = hours * (60 * 60) + (mins * 60) + secs +
875  cachedTimeInfo->local3amEpoch;
876  uint64_t nanoseconds = (seconds * one_billion);
877  if (fractionalUnits == one_billion) { // evaluated at compile-time
878  nanoseconds += fractionalUnits;
879  } else {
880  nanoseconds += ((fractionalUnits * one_billion) / UNITS) ;
881  }
882  return (nanoseconds);
883  }
884  // otherwise, no valid cache help available, so resort to mktime().
885 #ifdef _WIN32
886  CALL_TZSET();
887 #endif
888  // NOTE: in theory, mktime can fiddle with the tm_wday and
889  // tm_yday fields, so we cast away the constness
890  time_t seconds = mktime(const_cast<struct tm *>(&expandedTime));
891  uint64_t nanoseconds = (seconds * one_billion);
892  if (UNITS == one_billion) { // evaluated at compile-time
893  nanoseconds += fractionalUnits;
894  } else {
895  nanoseconds += (fractionalUnits * one_billion / UNITS) ;
896  }
897  return (nanoseconds);
898  }
899 
911  uint64_t convertToCustomEpochUnits(uint64_t desired_granularity=UNITS,
912  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) const {
913  // if cached info provided and for exact same day and after 3am
914  if ((cachedTimeInfo != nullptr) &&
915  (expandedTime.tm_mday == cachedTimeInfo->local3am.tm_mday) &&
916  (expandedTime.tm_mon == cachedTimeInfo->local3am.tm_mon) &&
917  (expandedTime.tm_year == cachedTimeInfo->local3am.tm_year) &&
918  (expandedTime.tm_hour >= 3)) { // 3 = 3am
919  // NOTE: for performance, we use the true constant values as
920  // there's no need to read them from memory and the subtract zero
921  // operations just collapse to logical assignments.
922  // Implied field documented in comment to right.
923  int hours = expandedTime.tm_hour - 3; // cachedTimedInfo->local3am.tv_hour;
924  int mins = expandedTime.tm_min - 0; // cachedTimedInfo->local3am.tv_min;
925  int secs = expandedTime.tm_sec - 0; // cachedTimedInfo->local3am.tv_sec;
926 #if 0 // By definition, 03:00:00 AM can't have these cases
927  if (secs < 0) {
928  secs += 60;
929  mins -= 1;
930  }
931  if (mins < 0) {
932  hours -= 1;
933  mins += 60;
934  }
935 #endif
936  uint64_t seconds = hours * (60 * 60) + (mins * 60) + secs +
937  cachedTimeInfo->local3amEpoch;
938  uint64_t units = (seconds * desired_granularity);
939 #ifdef _MSC_VER
940 #pragma warning(suppress : 4127)
941 #endif
942  if (desired_granularity == UNITS) { // if inlined, possibly evaluated at compile-time
943  units += fractionalUnits;
944  } else {
945  units += ((fractionalUnits * desired_granularity) / UNITS) ;
946  }
947  return (units);
948  }
949 #ifdef _WIN32
950  CALL_TZSET();
951 #endif
952  // NOTE: in theory, mktime can fiddle with the tm_wday and tm_yday fields
953  time_t seconds = mktime(const_cast<struct tm *>(&expandedTime));
954  uint64_t units = (seconds * desired_granularity) +
955  (fractionalUnits * desired_granularity / UNITS) ;
956  return (units);
957  }
958 
960  uint64_t getRelativeUnitsInDay() const {
961  uint64_t seconds = expandedTime.tm_sec +
962  expandedTime.tm_min * 60 +
963  expandedTime.tm_hour * 60 * 60;
964  uint64_t result = (seconds * UNITS) + fractionalUnits;
965  return (result);
966  }
967 
969  uint64_t getRelativeMicrosecondsInDay() const {
970  enum { one_million = 1000000 }; // for readability
971  uint64_t seconds = expandedTime.tm_sec +
972  expandedTime.tm_min * 60 +
973  expandedTime.tm_hour * 60 * 60;
974  uint64_t result = (seconds * one_million) +
975  ((fractionalUnits * one_million) / UNITS);
976  return (result);
977  }
978 
980  uint64_t getRelativeNanosecondsInDay() const {
981  enum { one_billion = 1000000000UL }; // for readability
982  uint64_t seconds = expandedTime.tm_sec +
983  expandedTime.tm_min * 60 +
984  expandedTime.tm_hour * 60 * 60;
985  uint64_t result = (seconds * one_billion) +
986  ((fractionalUnits * one_billion) / UNITS);
987  return (result);
988  }
989 
992  return (UNITS); // a constant, used for generic code
993  }
994 
1016  const char *convertDayAndTime(const char *dayAndTime,
1017  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) {
1018  memset(&expandedTime, 0, sizeof(expandedTime)); // clear
1019  expandedTime.tm_isdst = -1; // assert we don't have a clue
1020  fractionalUnits = 0;
1021  const char *cp = dayAndTime;
1022  while (*cp == ' ') ++cp; // skip any initial whitespace
1023  const char *fieldStart = cp;
1024  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1025  uint32_t fieldLen = (uint32_t) (cp - fieldStart);
1026  // OTHER DATABASE TIME: Mon N YYYY HH:MM:SS:fract{AM|PM}
1027  if (fieldLen == 8) { // YYYYMMDD
1028  expandedTime.tm_year = text2uint32(fieldStart, 4) - 1900;
1029  expandedTime.tm_mon = text2uint32(fieldStart + 4, 2) - 1;
1030  expandedTime.tm_mday = text2uint32(fieldStart + 6, 2);
1031  fieldStart = cp;
1032  } else if ((*cp == '/') || (*cp == '-')) { // YYYY-MM-DD
1033  expandedTime.tm_year = text2uint32(fieldStart, fieldLen);
1034  if (expandedTime.tm_year < 100) expandedTime.tm_year += 2000;
1035  expandedTime.tm_year -= 1900;
1036  fieldStart = ++cp;
1037  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1038  fieldLen = (uint32_t) (cp - fieldStart);
1039  expandedTime.tm_mon = text2uint32(fieldStart, fieldLen) - 1;
1040  fieldStart = ++cp;
1041  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1042  fieldLen = (uint32_t) (cp - fieldStart);
1043  expandedTime.tm_mday = text2uint32(fieldStart, fieldLen);
1044  fieldStart = cp;
1045  } else if (fieldLen == 0) { // hit characters at first...
1046  while ((*cp != ' ') && (*cp != '\0')) ++cp;
1047  fieldLen = (uint32_t) (cp - fieldStart);
1048  if (fieldLen < 3) { // don't recognize pattern
1049  return (fieldStart);
1050  }
1051  // NOTE: AND with ~0x20 forces ASCII lowercase to uppercase
1052  // THIS WILLL NOT WORK ON EBCDIC; ~0x40 would be used and the
1053  // compare would be against the lowercase variant or 0x40 would
1054  // be ORd in to permit the compare against the uppercase letter.
1055  expandedTime.tm_mon = 127; // invalid value as flag
1056  switch (fieldStart[0] & ~0x20) {
1057  case 'A': // APR,AUG
1058  switch (fieldStart[1] & ~0x20) {
1059  case 'P': // APR
1060  expandedTime.tm_mon = 4 - 1;
1061  break;
1062  case 'U': // AUG
1063  expandedTime.tm_mon = 8 - 1;
1064  break;
1065  }
1066  break;
1067  case 'D': // DEC
1068  expandedTime.tm_mon = 12 - 1;
1069  break;
1070  case 'F': // FEB
1071  expandedTime.tm_mon = 2 - 1;
1072  break;
1073  case 'J': // JAN,JUN,JUL
1074  switch (fieldStart[1] & ~0x20) {
1075  case 'A': // JAN
1076  expandedTime.tm_mon = 1 - 1;
1077  break;
1078  case 'U': // JUN,JUL
1079  switch (fieldStart[2] & ~0x20) {
1080  case 'L': // JUL
1081  expandedTime.tm_mon = 7 - 1;
1082  break;
1083  case 'N': // JUN
1084  expandedTime.tm_mon = 6 - 1;
1085  break;
1086  } // end switch third character
1087  break;
1088  } // end switch second character
1089  break;
1090  case 'M': // MAR,MAY
1091  switch (fieldStart[1] & ~0x20) {
1092  case 'A':
1093  switch (fieldStart[2] & ~0x20) {
1094  case 'R':
1095  expandedTime.tm_mon = 3 - 1;
1096  break;
1097  case 'Y':
1098  expandedTime.tm_mon = 5 - 1;
1099  break;
1100  }
1101  break;
1102  } // end switch third character
1103  break;
1104  case 'N': // NOV
1105  expandedTime.tm_mon = 11 - 1;
1106  break;
1107  case 'O': // OCT
1108  expandedTime.tm_mon = 10 - 1;
1109  break;
1110  case 'S': // SEP
1111  expandedTime.tm_mon = 9 - 1;
1112  break;
1113  } // end switch first character
1114  if (expandedTime.tm_mon == 127) { // failed to parse month name
1115  return (fieldStart);
1116  }
1117  while (*cp == ' ') ++cp; // skip any whitespace after month name
1118  fieldStart = cp;
1119  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1120  fieldLen = (uint32_t) (cp - fieldStart);
1121  expandedTime.tm_mday = text2uint32(fieldStart, fieldLen);
1122  while (*cp == ' ') ++cp; // skip any initial whitespace
1123  fieldStart = cp;
1124  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1125  fieldLen = (uint32_t) (cp - fieldStart);
1126  expandedTime.tm_year = text2uint32(fieldStart, fieldLen);
1127  expandedTime.tm_year -= 1900;
1128  fieldStart = cp;
1129  }
1130 
1131  if (cp == fieldStart) { // find end of field
1132  if ((*cp == '@') || (*cp == 'T')) {
1133  ++cp; // skip @ in YYYY/MM/DD@HH:MM:SS.mmmm
1134  } else {
1135  while (*cp == ' ') ++cp; // skip any initial whitespace
1136  }
1137  fieldStart = cp;
1138  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1139  }
1140  fieldLen = (uint32_t) (cp - fieldStart);
1141  if (fieldLen == 6) { // HHMMSS
1142  expandedTime.tm_hour = text2uint32(fieldStart, 2);
1143  expandedTime.tm_min = text2uint32(fieldStart + 2, 2);
1144  expandedTime.tm_sec = text2uint32(fieldStart + 4, 2);
1145  } else if (fieldLen == 4) { // HHMM
1146  expandedTime.tm_hour = text2uint32(fieldStart, 2);
1147  expandedTime.tm_min = text2uint32(fieldStart + 2, 2);
1148  expandedTime.tm_sec = 0; // implied
1149  } else if (fieldLen == 2) { // at least 3 fields with interfield separators
1150  expandedTime.tm_hour = text2uint32(fieldStart, fieldLen);
1151  if (*cp == ':') {
1152  fieldStart = ++cp; // skip over ":"
1153  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1154  fieldLen = (uint32_t) (cp - fieldStart);
1155  expandedTime.tm_min = text2uint32(fieldStart, fieldLen);
1156  if (*cp == ':') {
1157  fieldStart = ++cp; // skip over ":"
1158  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1159  fieldLen = (uint32_t) (cp - fieldStart);
1160  expandedTime.tm_sec = text2uint32(fieldStart, fieldLen);
1161  } else {
1162  expandedTime.tm_sec = 0;
1163  }
1164  } else {
1165  expandedTime.tm_min = 0;
1166  expandedTime.tm_sec = 0;
1167  }
1168  }
1169  // One database format used HH:MM:SS:fractional{A|P}M
1170  if ((*cp == '.') || (*cp == ':')) { // fractional units specified
1171  fieldStart = ++cp;
1172  while ((*cp >= '0') && (*cp <= '9')) ++cp;
1173  fieldLen = (uint32_t) (cp - fieldStart);
1174  uint32_t fraction = text2uint32(fieldStart, fieldLen);
1175  int tensPlaces = fieldLen;
1176  const int digitsWanted = int_digitsNeeded<UNITS>();
1177  while (tensPlaces < digitsWanted) { // not enough precision
1178  fraction *= 10;
1179  tensPlaces += 1;
1180  }
1181  while (tensPlaces > digitsWanted) { // too much, drop precision
1182  fraction /= 10;
1183  tensPlaces -= 1;
1184  }
1185  fractionalUnits = fraction;
1186  }
1187  if (*cp == 'Z') { // was in UTC
1188  int32_t utcSkew;
1189  if (cachedTimeInfo->isForDay(expandedTime)) {
1190  utcSkew = cachedTimeInfo->offsetFromUTC();
1191  } else {
1192  TimePointCache infoForDay(expandedTime);
1193  utcSkew = infoForDay.offsetFromUTC();
1194  }
1195 
1196  int32_t hours = utcSkew / (60 * 60);
1197  expandedTime.tm_hour += hours;
1198  utcSkew -= hours * (60 * 60);
1199  int32_t minutes = utcSkew / 60;
1200  expandedTime.tm_min += minutes;
1201  // TODO: check to see if tm_hour < 0 or > 23 and adjust tm_mday
1202  if (expandedTime.tm_hour < 0) {
1203  expandedTime.tm_hour += 24;
1204  expandedTime.tm_mday -= 1;
1205  if (expandedTime.tm_mday < 1) {
1206  // TODO: need to handle feb, etc.
1207  expandedTime.tm_mday = 31;
1208  expandedTime.tm_mon -= 1;
1209  if (expandedTime.tm_mon < 0) {
1210  expandedTime.tm_mon += 12;
1211  expandedTime.tm_year -= 1;
1212  }
1213  }
1214  }
1215  cp += 1; // skip 'Z'
1216  return (cp);
1217  }
1218  while (*cp == ' ') ++cp; // move to start of next field
1219  // Check for AM/PM suffix
1220  char c1 = *(cp) & ~0x20; // force to ASCII uppercase
1221  if ((c1 == 'P') &&
1222  ((*(cp + 1) & ~0x20) == 'M')) { // PM
1223  expandedTime.tm_hour += 12;
1224  cp += 2;
1225  } else if ((c1 == 'A') &&
1226  ((*(cp + 1) & ~0x20) == 'M')) { // AM
1227  cp += 2;
1228  }
1229  return (cp);
1230  }
1231 
1239  int convertDayAndTime(const char *day, const char *timeOfDay,
1240  const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) {
1241  char bfr[128];
1242 
1243  char *fieldEnd = (char *) memccpy(bfr, day, '\0', 32);
1244  if (fieldEnd == nullptr) {
1245  return (0);
1246  }
1247  *(fieldEnd - 1) = ' ';
1248  fieldEnd = (char *) memccpy(fieldEnd, timeOfDay, '\0', 32);
1249  if (fieldEnd == nullptr) {
1250  return (0);
1251  }
1252 
1253  const char *lastChar = convertDayAndTime(bfr, cachedTimeInfo);
1254  if (lastChar == bfr) {
1255  return (0);
1256  }
1257  return (1);
1258  }
1259 
1273  char *formatIntoString(char *bfr, uint_fast8_t bfrLen,
1274  uint_fast8_t *resultLen=nullptr,
1275  uint_fast8_t fieldsWanted=OUTPUT_DATE|OUTPUT_TIME,
1276  const char *fieldSeparators="/:. ") const
1277  {
1278  uint_fast8_t offset;
1279  uint_fast8_t field2Offset, field3Offset;
1280 
1281  if (fieldsWanted & OUTPUT_DATE) {
1282  int y = expandedTime.tm_year; // years from 1900
1283  if (fieldSeparators[0] != '\0') {
1284  field2Offset = 5;
1285  field3Offset = 8;
1286  offset = 10;
1287  bfr[4] = fieldSeparators[0];
1288  bfr[7] = fieldSeparators[0];
1289  } else {
1290  field2Offset = 4;
1291  field3Offset = 6;
1292  offset = 8;
1293  }
1294  memcpy(bfr, numberAs4Digits[y + 1900].digits, 4);
1295  memcpy(bfr+field2Offset, numberAsTwoDigits[expandedTime.tm_mon + 1], 2);
1296  memcpy(bfr+field3Offset, numberAsTwoDigits[expandedTime.tm_mday], 2);
1297  } else {
1298  offset = 0;
1299  }
1300  if (fieldsWanted & OUTPUT_TIME) {
1301  uint32_t fractBfr[6];
1302  const int fractionalLen = int_digitsNeeded<UNITS>(); // compile-time constant
1303  if ((offset != 0) && (fieldSeparators[3] != '\0')) {
1304  // output date and want a separator
1305  bfr[offset] = fieldSeparators[3];
1306  offset += 1;
1307  }
1308  uint_fast8_t fieldLen;
1309  if (fieldSeparators[1] != '\0') {
1310  field2Offset = offset + 3;
1311  field3Offset = offset + 6;
1312  fieldLen = 8;
1313  bfr[offset+2] = fieldSeparators[1];
1314  bfr[offset+5] = fieldSeparators[1];
1315  } else {
1316  field2Offset = offset + 2;
1317  field3Offset = offset + 4;
1318  fieldLen = 6;
1319  }
1320  memcpy(bfr+offset, numberAsTwoDigits[expandedTime.tm_hour], 2);
1321  memcpy(bfr+field2Offset, numberAsTwoDigits[expandedTime.tm_min], 2);
1322  memcpy(bfr+field3Offset, numberAsTwoDigits[expandedTime.tm_sec], 2);
1323  offset += fieldLen;
1324 
1325  if (fieldSeparators[2] != '\0') {
1326  bfr[offset] = fieldSeparators[2];
1327  offset += 1;
1328  }
1329 
1330  const char *fractText = uint_to_ascii_right_justified(fractBfr,
1331  sizeof(fractBfr), fractionalUnits, fractionalLen, '0');
1332  memcpy(bfr+offset, fractText, fractionalLen);
1333  offset += fractionalLen;
1334  }
1335  bfr[offset] = '\0';
1336  if (resultLen != nullptr) {
1337  *resultLen = offset;
1338  }
1339  return (bfr);
1340  }
1341 
1349  template <unsigned int ALT_UNITS> int compareDate(const TimePointOfGranularity<ALT_UNITS> &arg) const {
1350  int rc = expandedTime.tm_year - arg.expandedTime.tm_year;
1351  if (rc != 0) {
1352  return (rc);
1353  }
1354  rc = expandedTime.tm_mon - arg.expandedTime.tm_mon;
1355  if (rc != 0) {
1356  return (rc);
1357  }
1358  rc = expandedTime.tm_mday - arg.expandedTime.tm_mday;
1359  return (rc);
1360  }
1361 
1362 }; // end class TimePointOfGranularity<>
1363 
1366 
1369 
1371 template<typename STREAMTYPE, unsigned int UNITS>
1372 inline STREAMTYPE & operator<<(STREAMTYPE &o, const TimePointOfGranularity<UNITS> &t)
1373 {
1374  char bfr[64];
1375 
1376  o << t.formatIntoString(bfr, sizeof(bfr));
1377 
1378  return (o);
1379 }
1380 
1382 template <typename STREAMTYPE, unsigned int UNITS>
1383 inline STREAMTYPE & operator<<(STREAMTYPE &o, const POSIXtimeInUnits<UNITS> pt)
1384 {
1386  o << tp;
1387  return (o);
1388 }
1389 
1391 #endif
1392 /* vim: set expandtab shiftwidth=4 tabstop=4: */
TimePointCache::TimePointCache
TimePointCache(const struct tm &asIfOnDay)
Create a TimePointCache based around a local expanded time.
Definition: time_point.hpp:146
clock_gettime_via_tick
int clock_gettime_via_tick(struct timespec *result, bool force) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Definition: tick_time.h:290
TimePointOfGranularity::OUTPUT_DATE
@ OUTPUT_DATE
Definition: time_point.hpp:599
TimePointCacheTable::~TimePointCacheTable
~TimePointCacheTable()
Definition: time_point.hpp:278
TimePointCacheForToday
TimePointCache TimePointCacheForToday
Cached TimePoint information representing today.
TimePointCache::lastTime
struct tm lastTime
Definition: time_point.hpp:103
TimePointCache::localEndOfDay
struct tm localEndOfDay
Definition: time_point.hpp:101
TimePointCache::local3amEpoch
time_t local3amEpoch
Definition: time_point.hpp:107
TimePointCache::utcDifferenceSeconds
int32_t utcDifferenceSeconds
Definition: time_point.hpp:109
POSIXtimeInUnits::POSIXtimeInUnits
POSIXtimeInUnits(time_t seconds, int64_t fractional, int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Construct a POSIXtimeInUnits from seconds since the POSIX epoch.
Definition: time_point.hpp:425
POSIXtimeInUnits::operator=
POSIXtimeInUnits< UNITS > & operator=(const TimeWithNanoseconds time_ns) OME_ALWAYS_INLINE
Assignment operator from TimeWithNanoseconds structure.
Definition: time_point.hpp:464
TimePointOfGranularity::expandedTime
struct tm expandedTime
Locale-specific time, conforms to POSIX, C89 and onwards.
Definition: time_point.hpp:602
get_time.h
Time acquisition routines.
TimePointOfGranularity::fractionalUnits
uint64_t fractionalUnits
Fractional seconds in granularity of UNITS-per-second.
Definition: time_point.hpp:603
time_point.hpp
FARGOS Time Functions.
TimedMutex::unlock
int64_t unlock()
Release a previously locked mutex.
Definition: timed_mutex.cpp:156
TimePointCacheTable::timeTable
std::map< time_t, TimePointCache * > timeTable
Definition: time_point.hpp:272
POSIXtimeInUnits::assignFromTimeWithNanoseconds
void assignFromTimeWithNanoseconds(const TimeWithNanoseconds time_ns, const int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Definition: time_point.hpp:317
TimePointOfGranularity::formatIntoString
char * formatIntoString(char *bfr, uint_fast8_t bfrLen, uint_fast8_t *resultLen=nullptr, uint_fast8_t fieldsWanted=OUTPUT_DATE|OUTPUT_TIME, const char *fieldSeparators="/:. ") const
Format into text string.
Definition: time_point.hpp:1273
TimePointOfGranularity::convertDayAndTime
int convertDayAndTime(const char *day, const char *timeOfDay, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Convert strings representing date and time into expanded time structure.
Definition: time_point.hpp:1239
CALL_TZSET
#define CALL_TZSET()
Definition: time_point.hpp:53
POSIXtimeInUnits::time_in_units
uint64_t time_in_units
holds total UNITS since POSIX epoch
Definition: time_point.hpp:315
uint_to_ascii_right_justified
char * uint_to_ascii_right_justified(uint32_t resultBfr[], uint_fast8_t bfrLen, uint64_t value, uint_fast8_t fieldLen, char fillChar)
Convert a binary integer into right-justified ASCII decimal text and pad on the left with a specified...
Definition: text2int.cpp:2718
TimePointOfGranularity::getRelativeUnitsInDay
uint64_t getRelativeUnitsInDay() const
Get relative units within a day.
Definition: time_point.hpp:960
POSIXtimeInUnits::operator<=
bool operator<=(const POSIXtimeInUnits< ALT_UNITS > arg) const
Less-than-or-equal comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:521
TimePointCache
Cache locale-specific time data around a particular point in time.
Definition: time_point.hpp:92
TimePointOfGranularity::OUTPUT_TIME
@ OUTPUT_TIME
Definition: time_point.hpp:600
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity(time_t secondsSinceEpoch, uint64_t fraction=0, int skewByMinutes=0, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Construct from seconds from POSIX epoch and optional fractional component and skew from localtime.
Definition: time_point.hpp:799
TimePointCache::TimePointCache
TimePointCache(const time_t asOfPOSIXepoch)
Create a TimePointCache based around a specific point in time.
Definition: time_point.hpp:124
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity(const char *day, const char *timeOfDay, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Construct from text string specifying date and time.
Definition: time_point.hpp:781
numberAs4Digits
const union Aligned4Chars numberAs4Digits[10000]
Definition: text2int.cpp:124
TimePointCache::lastTimeEpoch
time_t lastTimeEpoch
Definition: time_point.hpp:108
OME_ALWAYS_OPTIMIZE
#define OME_ALWAYS_OPTIMIZE(level)
Mark a function to be compiled with a specific level of optimization.
Definition: compiler_hints.h:406
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity()
Null constructor, leaves in undefined state.
Definition: time_point.hpp:716
POSIXtimeInUnits::operator<
bool operator<(const POSIXtimeInUnits< ALT_UNITS > arg) const
Less-than comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:543
TimeWithNanoseconds
Structure for representing time as relative seconds and nanoseconds.
Definition: get_time.h:24
POSIXtimeInUnits::operator>
bool operator>(const POSIXtimeInUnits< ALT_UNITS > arg) const
Greater-than comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:554
TimePointOfGranularity::initializeWithUnitsFromEpoch
void initializeWithUnitsFromEpoch(time_t secondsSinceEpoch, uint64_t fractionInUnits, int skewByMinutes=0, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Initialize with seconds from POSIX epoch, fractional component and optional skew from localtime.
Definition: time_point.hpp:622
TimePointCache::utc3am
struct tm utc3am
Definition: time_point.hpp:104
TimePointCache::TimePointCache
TimePointCache(const struct timespec &asIfOnDay)
Create a TimePointCache around a time expressed as a timespec, which is represented using the POSIX e...
Definition: time_point.hpp:138
TimePointCache::isForDay
bool isForDay(const struct tm &dayOfInterest) const
Definition: time_point.hpp:245
POSIXtimeInUnits::getSeconds
time_t getSeconds() const OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Convert a POSIXtimeInUnits to seconds since the POSIX epoch.
Definition: time_point.hpp:489
TimePointOfGranularity::getUnitsPerSecond
static CONSTEXPR uint64_t getUnitsPerSecond() OME_CONST_FUNCTION OME_ALWAYS_INLINE
Get units per second represented by fractional component.
Definition: time_point.hpp:991
TimeWithNanoseconds::time_nanosec
uint64_t time_nanosec
Definition: get_time.h:26
srcID
const char srcID[]
Definition: catSym.c:17
POSIXtimeInUnits::operator>=
bool operator>=(const POSIXtimeInUnits< ALT_UNITS > arg) const
Greater-than-or-equal comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:532
timed_mutex.hpp
TimePointOfGranularity::operator=
TimePointOfGranularity< UNITS > & operator=(const struct tm &POSIXexpandedDate)
assignment operator from a tm structure.
Definition: time_point.hpp:831
TimePointCache::local3am
struct tm local3am
Definition: time_point.hpp:102
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity(const struct tm &explodedTime, uint64_t fraction=0)
Construct from standard broken-out time structure.
Definition: time_point.hpp:724
TimePointCache::isForDay
bool isForDay(const time_t t) const OME_ALWAYS_INLINE
Definition: time_point.hpp:201
TimePointCache::localEndOfDayEpoch
time_t localEndOfDayEpoch
Definition: time_point.hpp:106
POSIXtimeInSeconds
POSIXtimeInUnits< 1U > POSIXtimeInSeconds
Convenience typedef for conventional 1-second resolution time.
Definition: time_point.hpp:587
TimePointOfGranularity::compareDate
int compareDate(const TimePointOfGranularity< ALT_UNITS > &arg) const
Compare the date portion of a TimePointOfGranularity.
Definition: time_point.hpp:1349
TimePointOfGranularity::operator=
TimePointOfGranularity< UNITS > & operator=(const TimePointOfGranularity< INCOMING_UNITS > &arg)
assignment operator from a TimePointOfGranularity object.
Definition: time_point.hpp:809
int_digitsNeeded
CONSTEXPR unsigned int int_digitsNeeded() OME_CONST_FUNCTION OME_ALWAYS_INLINE
Via compile-time evaluation, compute log10(). Used to determine number digits required to display pre...
Definition: time_point.hpp:61
POSIXtimeInUnits::convertToNanosecondsSinceEpoch
uint64_t convertToNanosecondsSinceEpoch() const OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Convert a POSIXtimeInUnits to nanoseconds since the POSIX epoch.
Definition: time_point.hpp:471
POSIXEpochTimePoint
TimePointOfGranularity< 1 > POSIXEpochTimePoint
Convenience typedef using conventional 1-second resolution.
Definition: time_point.hpp:1368
numberAsTwoDigits
const char numberAsTwoDigits[100][3]
Table of 2-character strings representing 00-99.
Definition: text2int.cpp:20
TimePointOfGranularity
Representation of localized expanded UNITS-since-epoch.
Definition: time_point.hpp:596
TimePointCache::initializeForDay
void initializeForDay(const struct tm &asIfOnDay)
Initialize a TimePointCache around an already expanded time, which is intended to reflect a local tim...
Definition: time_point.hpp:154
operator<<
STREAMTYPE & operator<<(STREAMTYPE &o, const TimePointOfGranularity< UNITS > &t)
Output TimePointOfGranularity as text onto a stream-like object.
Definition: time_point.hpp:1372
POSIXtimeInUnits
Representation of UNITS-since-POSIX-epoch. This is an unambiguous time reference; there is no locale-...
Definition: time_point.hpp:313
TimePointCache::initializeForDay
void initializeForDay(const struct timespec &asIfOnDay)
Initialize a TimePointCache around a time specified using a timespec, which is based on the POSIX epo...
Definition: time_point.hpp:189
text2uint32
uint_fast32_t text2uint32(const char *textString, uint_fast8_t text_len) NONNULL_PARAMETERS(1) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Convert a sequence of text characters into an unsigned integer as quickly as possible....
Definition: text2int.h:79
TimedMutex
Generic mutex implementation that supports timing statistics.
Definition: timed_mutex.hpp:51
text2int.h
Extreme-performance text/number conversion routines.
int_digitsNeeded< 0 >
CONSTEXPR unsigned int int_digitsNeeded< 0 >()
Termination condition for safety.
Definition: time_point.hpp:73
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity(const POSIXtimeInUnits< PT_UNITS > ptTime, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday, int skewByMinutes=0)
Construct from arbitrary POSIXtimeInUnits<> object.
Definition: time_point.hpp:741
TimePointOfGranularity::getRelativeNanosecondsInDay
uint64_t getRelativeNanosecondsInDay() const
Get relative nanoseconds within a day.
Definition: time_point.hpp:980
POSIXtimeInUnits::operator!=
bool operator!=(const POSIXtimeInUnits< ALT_UNITS > arg) const
Inequality comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:510
POSIXtimeInUnits::POSIXtimeInUnits
POSIXtimeInUnits(const TimeWithNanoseconds time_ns, int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Construct a POSIXtimeInUnits from a TimeWithNanoseconds structure.
Definition: time_point.hpp:444
POSIXtimeInUnits::operator==
bool operator==(const POSIXtimeInUnits< ALT_UNITS > arg) const
Equality comparison against a POSIXtimeInUnits of arbitrary granularity.
Definition: time_point.hpp:499
OME_USED
const char srcID[] OME_USED
Definition: tick_time.cpp:24
TimePointOfGranularity::TimePointOfGranularity
TimePointOfGranularity(const char *dayAndTime, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Construct from text string specifying date and time.
Definition: time_point.hpp:768
POSIXtimeInUnits::getCurrentTime
static POSIXtimeInUnits< UNITS > getCurrentTime() OME_ALWAYS_INLINE
Get the current time as units-since-the-POSIX epoch.
Definition: time_point.hpp:564
TimePointCacheTable::TimePointCacheTable
TimePointCacheTable(const char *tableName="timeCache")
Definition: time_point.hpp:274
TimePointCacheTable::getCacheEntry
const TimePointCache & getCacheEntry(time_t t)
Returns a TimePointCache entry for the day indicated by the number of seconds since the POSIX epoch.
Definition: time_point.hpp:292
OME_CONST_FUNCTION
#define OME_CONST_FUNCTION
Mark as an idempotent function that only accesses arguments – no global data.
Definition: compiler_hints.h:390
TimeWithNanoseconds::time_sec
uint64_t time_sec
Definition: get_time.h:25
POSIXtimeInUnits::convertToCustomEpochUnits
uint64_t convertToCustomEpochUnits(uint64_t desired_granularity=UNITS) const OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Converts from a POSIXtimeInUnits to an arbitrary granularity.
Definition: time_point.hpp:351
SharedMemoryVariableManager
Manager for collection of shared memory variables.
Definition: shared_variable.hpp:193
TimePointOfGranularity::convertDayAndTime
const char * convertDayAndTime(const char *dayAndTime, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday)
Convert string representing day and time into expanded time structure.
Definition: time_point.hpp:1016
TimePointOfGranularity::convertToNanosecondsSinceEpoch
uint64_t convertToNanosecondsSinceEpoch(const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) const
Convert expanded time to nanoseconds since POSIX epoch.
Definition: time_point.hpp:849
NanosecondTimePoint
TimePointOfGranularity< 1000000000 > NanosecondTimePoint
Desired standard granularity with nanosecond resolution.
Definition: time_point.hpp:1365
compiler_hints.h
Compiler-specific macros to provide performance-related hints.
OME_ALWAYS_INLINE
#define OME_ALWAYS_INLINE
Tell the compiler to alway inline a function, regardless of optimization level.
Definition: compiler_hints.h:364
powerOf10Constant
CONSTEXPR uint64_t powerOf10Constant() OME_CONST_FUNCTION OME_ALWAYS_INLINE
Generate compile-time constant for integral power of 10.
Definition: text2int.h:678
TimePointOfGranularity::initializeWithNanosecondsFromEpoch
void initializeWithNanosecondsFromEpoch(uint64_t nanosecondsSinceEpoch, time_t secondsSinceEpoch=0, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday, int skewByMinutes=0) OME_ALWAYS_INLINE OME_ALWAYS_OPTIMIZE("-O3")
Initialize with time specified as nanoseconds from POSIX epoch.
Definition: time_point.hpp:681
OME_INIT_PRIORITY
TimePointCache TimePointCacheForToday OME_INIT_PRIORITY(109)((time_t) 0)
TimePointOfGranularity::convertToCustomEpochUnits
uint64_t convertToCustomEpochUnits(uint64_t desired_granularity=UNITS, const TimePointCache *cachedTimeInfo=&TimePointCacheForToday) const
Convert expanded time to custom units since POSIX epoch.
Definition: time_point.hpp:911
tick_time.h
FARGOS CPU tick routines.
TimePointCache::localMidnight
struct tm localMidnight
Definition: time_point.hpp:100
TimePointCache::offsetFromUTC
int32_t offsetFromUTC() const OME_ALWAYS_INLINE
Definition: time_point.hpp:241
TimePointCache::initializeForDay
void initializeForDay(const time_t asOfPOSIXepoch)
Initialize a TimePointCache based around a specific point in time.
Definition: time_point.hpp:223
TimePointCache::localMidnightEpoch
time_t localMidnightEpoch
Definition: time_point.hpp:105
TimePointOfGranularity::getRelativeMicrosecondsInDay
uint64_t getRelativeMicrosecondsInDay() const
Get relative microseconds within a day.
Definition: time_point.hpp:969
TimePointCacheTable::tblLock
TimedMutex tblLock
Definition: time_point.hpp:271
CONSTEXPR
#define CONSTEXPR
Generates constexpr if the compiler supports it.
Definition: compiler_hints.h:432
TimePointCacheTable
Convenience class to maintain a table of TimePointCache objects.
Definition: time_point.hpp:269
POSIXtimeInNanoseconds
POSIXtimeInUnits< 1000000000U > POSIXtimeInNanoseconds
Convenience typedef for nanosecond-resolution time.
Definition: time_point.hpp:580
TimePointCache::TimePointCache
TimePointCache()
Null constructor that does no work.
Definition: time_point.hpp:114
int_digitsNeeded< 1 >
CONSTEXPR unsigned int int_digitsNeeded< 1 >()
\brief Special case for unit precision of 1–no decimal point needed
Definition: time_point.hpp:67
Generated: Fri Jul 31 2020 18:19:15
Support Information