1#ifndef REMORA_TimeUnits_H
2#define REMORA_TimeUnits_H
54inline std::string
lower (std::string
s)
59 c = (
c ==
'\0') ?
' ' :
static_cast<char>(std::tolower(
static_cast<unsigned char>(
c)));
67 int h = 0,
m = 0, n = 0;
69 bool matched = (std::sscanf(
tok.c_str(),
"%d:%d:%lf%n", &
h, &
m, &
s, &n) == 3);
73 matched = (std::sscanf(
tok.c_str(),
"%d:%d%n", &
h, &
m, &n) == 2);
78 const std::string
rest =
tok.substr(n);
92 int y = 0,
mo = 0,
d = 0, n = 0;
93 if (std::sscanf(
tok.c_str(),
"%d-%d-%d%n", &
y, &
mo, &
d, &n) != 3) {
96 const std::string
rest =
tok.substr(n);
115 static const char*
const names[] = {
"utc",
"gmt",
"z",
"+0",
"-0",
"+00",
"-00",
116 "+0:00",
"-0:00",
"+00:00",
"-00:00",
118 for (
const char* name :
names) {
119 if (
tok == name) {
return true; }
143 std::vector<std::string>
tok;
145 std::istringstream
iss(lower(
units));
147 while (
iss >> w) {
tok.push_back(w); }
150 error =
"the units attribute is empty";
156 while (
i <
tok.size() &&
tok[
i] !=
"since") { ++
i; }
157 if (
i ==
tok.size()) {
163 for (++
i;
i <
tok.size(); ++
i) {
164 if (parse_date(
tok[
i],
out)) {
break; }
166 if (
i ==
tok.size()) {
167 error =
"no date of the form yyyy-mm-dd follows 'since'";
170 out.has_reference =
true;
173 if (
i <
tok.size() && parse_clock(
tok[
i],
out)) { ++
i; }
174 if (
i <
tok.size()) {
175 if (!is_utc(
tok[
i])) {
176 error =
"'" +
tok[
i] +
"' is not a time of day or UTC; reference dates in"
177 " another time zone are not supported";
182 if (
i <
tok.size()) {
183 error =
"unexpected '" +
tok[
i] +
"' after the reference date";
187 if (
out.month < 1 ||
out.month > 12 ||
out.day < 1 ||
out.day > 31 ||
188 out.hour < 0 ||
out.hour > 23 ||
out.minute < 0 ||
out.minute > 59 ||
189 out.second < 0.0 ||
out.second >= 61.0) {
190 error =
"the reference date is out of range";
206 if (!
units.has_reference) {
226 const std::string name =
c.substr(0,
c.find_last_not_of(
' ') + 1);
227 if (
static_cast<int>(time_ref) == -1) {
228 return name ==
"360_day";
230 return name ==
"gregorian" || name ==
"standard" || name ==
"proleptic_gregorian";
236 char buf[6 * 11 + 5 + 1];
237 std::snprintf(
buf,
sizeof(
buf),
"%04d-%02d-%02d %02d:%02d:%02d",
239 static_cast<int>(
units.second));
240 return std::string(
buf);
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE double remora_datenum(double time_ref, int year, int month, int day, int hour=0, int minutes=0, double seconds=0.0) noexcept
Fractional day number for a calendar date. ROMS datenum.
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE double remora_ref_datenum(double time_ref) noexcept
Day number of the reference date implied by time_ref.
mf_h setVal(geomdata.ProbHi(2))
bool remora_calendar_matches_time_ref(const std::string &calendar, double time_ref)
Whether a CF calendar attribute names the calendar time_ref selects.
bool remora_parse_time_units(const std::string &units, REMORATimeUnits &out, std::string &error)
Parse a CF time-units attribute.
std::string remora_time_units_date_string(const REMORATimeUnits &units)
The reference date of units as YYYY-MM-DD hh:mm:ss.
double remora_time_units_offset_days(const REMORATimeUnits &units, double time_ref)
Days to add to a time counted from units' reference date to count it from the date time_ref names ins...
std::string lower(std::string s)
bool parse_clock(const std::string &tok, REMORATimeUnits &out)
hh:mm[:ss[.s]], optionally suffixed z. Fills the time fields on success.
bool is_utc(const std::string &tok)
A time-zone designator that means UTC.
bool parse_date(const std::string &tok, REMORATimeUnits &out)
A parsed CF time-units attribute.
std::string unit
The unit word, lower-cased: days, seconds, ...
bool has_reference
Whether a since <date> reference date followed the unit.