static int find_next(const CalendarSpec *spec, struct tm *tm) { struct tm c; int r; assert(spec); assert(tm); c = *tm; for (;;) { /* Normalize the current date */ mktime(&c); c.tm_isdst = -1; c.tm_year += 1900; r = find_matching_component(spec->year, &c.tm_year); c.tm_year -= 1900; if (r > 0) { c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = 0; } if (r < 0 || tm_out_of_bounds(&c)) return r; c.tm_mon += 1; r = find_matching_component(spec->month, &c.tm_mon); c.tm_mon -= 1; if (r > 0) { c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = 0; } if (r < 0 || tm_out_of_bounds(&c)) { c.tm_year ++; c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = 0; continue; } r = find_matching_component(spec->day, &c.tm_mday); if (r > 0) c.tm_hour = c.tm_min = c.tm_sec = 0; if (r < 0 || tm_out_of_bounds(&c)) { c.tm_mon ++; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = 0; continue; } if (!matches_weekday(spec->weekdays_bits, &c)) { c.tm_mday++; c.tm_hour = c.tm_min = c.tm_sec = 0; continue; } r = find_matching_component(spec->hour, &c.tm_hour); if (r > 0) c.tm_min = c.tm_sec = 0; if (r < 0 || tm_out_of_bounds(&c)) { c.tm_mday ++; c.tm_hour = c.tm_min = c.tm_sec = 0; continue; } r = find_matching_component(spec->minute, &c.tm_min); if (r > 0) c.tm_sec = 0; if (r < 0 || tm_out_of_bounds(&c)) { c.tm_hour ++; c.tm_min = c.tm_sec = 0; continue; } r = find_matching_component(spec->second, &c.tm_sec); if (r < 0 || tm_out_of_bounds(&c)) { c.tm_min ++; c.tm_sec = 0; continue; } *tm = c; return 0; } }
static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { struct tm c; int tm_usec; int r; assert(spec); assert(tm); c = *tm; tm_usec = *usec; for (;;) { /* Normalize the current date */ (void) mktime_or_timegm(&c, spec->utc); c.tm_isdst = spec->dst; c.tm_year += 1900; r = find_matching_component(spec, spec->year, &c, &c.tm_year); c.tm_year -= 1900; if (r > 0) { c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; } if (r < 0) return r; if (tm_out_of_bounds(&c, spec->utc)) return -ENOENT; c.tm_mon += 1; r = find_matching_component(spec, spec->month, &c, &c.tm_mon); c.tm_mon -= 1; if (r > 0) { 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)) { c.tm_year++; c.tm_mon = 0; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 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)) { c.tm_mon++; c.tm_mday = 1; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) { c.tm_mday++; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; continue; } 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)) { c.tm_mday++; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; 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)) { c.tm_hour++; c.tm_min = c.tm_sec = tm_usec = 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)) { c.tm_min++; c.tm_sec = tm_usec = 0; continue; } *tm = c; *usec = tm_usec; return 0; } }