ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
ERF_EpochTime.H File Reference
#include <string>
#include <sstream>
#include <iomanip>
#include <ctime>
#include <cctype>
#include <cmath>
#include <cstdio>
Include dependency graph for ERF_EpochTime.H:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AMREX_GPU_HOST AMREX_FORCE_INLINE bool parse_fixed_width_int (const char *&dt, int width, int &value)
 
AMREX_GPU_HOST AMREX_FORCE_INLINE std::time_t getEpochTime (const std::string &dateTime, const std::string &dateTimeFormat)
 
AMREX_FORCE_INLINE std::string getTimestamp (const double epoch_real, const std::string &datetime_format, bool add_long_frac=true)
 

Function Documentation

◆ getEpochTime()

AMREX_GPU_HOST AMREX_FORCE_INLINE std::time_t getEpochTime ( const std::string &  dateTime,
const std::string &  dateTimeFormat 
)

Convert a formatted date-time string to epoch time.

Parameters
[in]dateTimeString containing the date and time.
[in]dateTimeFormatFormat string describing the layout of dateTime.
Returns
Epoch time as std::time_t, or -1 on failure.
50 {
51  std::tm tmTime{};
52  const char* dt = dateTime.c_str();
53  const char* fmt = dateTimeFormat.c_str();
54 
55  // Walk both the format string and the date string together
56  while (*fmt && *dt) {
57  if (*fmt == '%') {
58  ++fmt;
59  int parsed_value = 0;
60  switch (*fmt) {
61  case 'Y': // 4-digit year
62  if (!parse_fixed_width_int(dt, 4, parsed_value)) return -1;
63  tmTime.tm_year = parsed_value;
64  tmTime.tm_year -= 1900;
65  break;
66  case 'm': // 2-digit month
67  if (!parse_fixed_width_int(dt, 2, parsed_value)) return -1;
68  tmTime.tm_mon = parsed_value;
69  tmTime.tm_mon -= 1; // struct tm expects 0-11
70  break;
71  case 'd': // 2-digit day
72  if (!parse_fixed_width_int(dt, 2, parsed_value)) return -1;
73  tmTime.tm_mday = parsed_value;
74  break;
75  case 'H': // 2-digit hour
76  if (!parse_fixed_width_int(dt, 2, parsed_value)) return -1;
77  tmTime.tm_hour = parsed_value;
78  break;
79  case 'M': // 2-digit minute
80  if (!parse_fixed_width_int(dt, 2, parsed_value)) return -1;
81  tmTime.tm_min = parsed_value;
82  break;
83  case 'S': // 2-digit second
84  if (!parse_fixed_width_int(dt, 2, parsed_value)) return -1;
85  tmTime.tm_sec = parsed_value;
86  break;
87  default:
88  // Unsupported format specifier
89  return -1;
90  }
91  } else {
92  // Literal character, must match
93  if (*fmt != *dt) {
94  return -1; // mismatch
95  }
96  ++dt;
97  }
98  ++fmt;
99  }
100 
101  if (*fmt != '\0' || *dt != '\0') {
102  return -1;
103  }
104 
105  if (tmTime.tm_mon < 0 || tmTime.tm_mon > 11 ||
106  tmTime.tm_mday < 1 || tmTime.tm_mday > 31 ||
107  tmTime.tm_hour < 0 || tmTime.tm_hour > 23 ||
108  tmTime.tm_min < 0 || tmTime.tm_min > 59 ||
109  tmTime.tm_sec < 0 || tmTime.tm_sec > 60) {
110  return -1;
111  }
112 
113  return timegm(&tmTime);
114 }
AMREX_GPU_HOST AMREX_FORCE_INLINE bool parse_fixed_width_int(const char *&dt, int width, int &value)
Definition: ERF_EpochTime.H:25

Referenced by ERF::ReadParameters().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getTimestamp()

AMREX_FORCE_INLINE std::string getTimestamp ( const double  epoch_real,
const std::string &  datetime_format,
bool  add_long_frac = true 
)

Convert epoch time to a formatted timestamp string.

Parameters
[in]epoch_realEpoch time in seconds.
[in]datetime_formatFormat string for the resulting timestamp.
[in]add_long_fracWhether to append fractional seconds to the output.
Returns
Formatted timestamp string.
126 {
127  std::time_t epoch_nearest_sec;
128  long long frac_usec = 0;
129 
130  if (add_long_frac) {
131  //
132  // NOTE: when we print the fraction we must derive it and the whole seconds from
133  // the *same* rounded value. If we instead truncated the seconds and then
134  // printed the leftover fraction to six places, a fraction just below one
135  // would print as "1.000000" next to the un-incremented second and the
136  // timestamp would come out a full second early.
137  //
138  // We round to the microsecond we are about to print, then split, rounding the
139  // seconds toward -infinity so that the fraction is never negative -- which
140  // also gives the right answer for times before the epoch.
141  //
142  constexpr long long usec_per_sec = 1000000;
143  const long long total_usec = std::llround(epoch_real * 1.e6);
144  long long whole_sec = total_usec / usec_per_sec;
145  frac_usec = total_usec % usec_per_sec;
146  if (frac_usec < 0) { whole_sec -= 1; frac_usec += usec_per_sec; }
147  epoch_nearest_sec = static_cast<std::time_t>(whole_sec);
148  } else {
149  epoch_nearest_sec = static_cast<std::time_t>(epoch_real);
150  }
151 
152  std::tm *time_info = std::gmtime(&epoch_nearest_sec);
153 
154  char buffer[80];
155  std::strftime(buffer, sizeof(buffer), datetime_format.c_str(), time_info);
156  std::string str_nearest_sec(buffer);
157 
158  if (add_long_frac) {
159  snprintf(buffer, 80, ".%06lld", frac_usec);
160  return str_nearest_sec + std::string(buffer);
161  } else {
162  return str_nearest_sec;
163  }
164 }

Referenced by ERF::Evolve(), ERF::Write3DPlotFile(), ERF::writeJobInfo(), and ERF::WriteSubvolume().

Here is the caller graph for this function:

◆ parse_fixed_width_int()

AMREX_GPU_HOST AMREX_FORCE_INLINE bool parse_fixed_width_int ( const char *&  dt,
int  width,
int &  value 
)

Parse an integer of fixed width from a string.

Parameters
[in,out]dtString to parse from; advanced by width on success.
[in]widthNumber of characters to parse.
[out]valueParsed integer value.
Returns
True if parsing was successful, false otherwise.
26 {
27  value = 0;
28 
29  for (int idx = 0; idx < width; ++idx) {
30  unsigned char ch = static_cast<unsigned char>(dt[idx]);
31  if (ch == '\0' || !std::isdigit(ch)) {
32  return false;
33  }
34  value = 10 * value + (dt[idx] - '0');
35  }
36 
37  dt += width;
38  return true;
39 }
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE int idx(int i, int j, int k, int nx, int ny)
Definition: ERF_InitForEnsemble.cpp:365

Referenced by getEpochTime().

Here is the call graph for this function:
Here is the caller graph for this function: