return r;
}
-static bool tm_out_of_bounds(const struct tm *tm, bool utc) {
+static int tm_within_bounds(struct tm *tm, bool utc) {
struct tm t;
assert(tm);
- t = *tm;
-
- if (mktime_or_timegm(&t, utc) < 0)
- return true;
-
/*
* Set an upper bound on the year so impossible dates like "*-02-31"
* don't cause find_next() to loop forever. tm_year contains years
* since 1900, so adjust it accordingly.
*/
if (tm->tm_year + 1900 > MAX_YEAR)
- return true;
+ return -ERANGE;
+
+ t = *tm;
+ if (mktime_or_timegm(&t, utc) < 0)
+ return negative_errno();
/* Did any normalization take place? If so, it was out of bounds before */
- return
- t.tm_year != tm->tm_year ||
- t.tm_mon != tm->tm_mon ||
- t.tm_mday != tm->tm_mday ||
- t.tm_hour != tm->tm_hour ||
- t.tm_min != tm->tm_min ||
- t.tm_sec != tm->tm_sec;
+ bool good = t.tm_year == tm->tm_year &&
+ t.tm_mon == tm->tm_mon &&
+ t.tm_mday == tm->tm_mday &&
+ t.tm_hour == tm->tm_hour &&
+ t.tm_min == tm->tm_min &&
+ t.tm_sec == tm->tm_sec;
+ if (!good)
+ *tm = t;
+ return good;
}
static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
}
if (r < 0)
return r;
- if (tm_out_of_bounds(&c, spec->utc))
+ if (tm_within_bounds(&c, spec->utc) <= 0)
return -ENOENT;
c.tm_mon += 1;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
}
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
+ if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_year++;
c.tm_mon = 0;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
+ if (r == 0)
+ continue;
r = find_matching_component(spec, spec->day, &c, &c.tm_mday);
if (r > 0)
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
+ if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_mon++;
c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
+ if (r == 0)
+ continue;
if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
c.tm_mday++;
r = find_matching_component(spec, spec->hour, &c, &c.tm_hour);
if (r > 0)
c.tm_min = c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
+ if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_mday++;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
+ if (r == 0)
+ /* The next hour we set might be missing if there
+ * are time zone changes. Let's try again starting at
+ * normalized time. */
+ continue;
r = find_matching_component(spec, spec->minute, &c, &c.tm_min);
if (r > 0)
c.tm_sec = tm_usec = 0;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
+ if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_hour++;
c.tm_min = c.tm_sec = tm_usec = 0;
continue;
}
+ if (r == 0)
+ continue;
c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec;
r = find_matching_component(spec, spec->microsecond, &c, &c.tm_sec);
tm_usec = c.tm_sec % USEC_PER_SEC;
c.tm_sec /= USEC_PER_SEC;
- if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
+ if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_min++;
c.tm_sec = tm_usec = 0;
continue;
}
+ if (r == 0)
+ continue;
*tm = c;
*usec = tm_usec;