+int timestamp_from_arg(const char *arg,
+ struct trimmer_bound *result_bound, bool gmt)
+{
+ int ret;
+ int64_t value;
+ unsigned int year, month, day, hh, mm, ss, ns;
+
+ /* YYYY-MM-DD hh:mm:ss.ns */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
+ &year, &month, &day, &hh, &mm, &ss, &ns);
+ if (ret == 7) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+ time_t result;
+
+ if (gmt) {
+ result = timegm(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ } else {
+ result = mktime(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ }
+ value = (int64_t) result;
+ value *= NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+ /* hh:mm:ss.ns */
+ ret = sscanf(arg, "%u:%u:%u.%u",
+ &hh, &mm, &ss, &ns);
+ if (ret == 4) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = ns;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ }
+ /* -ss.ns */
+ ret = sscanf(arg, "-%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = -ss * NSEC_PER_SEC;
+ value -= ns;
+ goto set;
+ }
+ /* ss.ns */
+ ret = sscanf(arg, "%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = ss * NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+
+ /* YYYY-MM-DD hh:mm:ss */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
+ &year, &month, &day, &hh, &mm, &ss);
+ if (ret == 6) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+
+ if (gmt) {
+ value = timegm(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ } else {
+ value = mktime(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ }
+ value *= NSEC_PER_SEC;
+ goto set;
+ }
+ /* hh:mm:ss */
+ ret = sscanf(arg, "%u:%u:%u",
+ &hh, &mm, &ss);
+ if (ret == 3) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = 0;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ }
+ /* -ss */
+ ret = sscanf(arg, "-%u",
+ &ss);
+ if (ret == 1) {
+ value = -ss * NSEC_PER_SEC;
+ goto set;
+ }
+ /* ss */
+ ret = sscanf(arg, "%u",
+ &ss);
+ if (ret == 1) {
+ value = ss * NSEC_PER_SEC;
+ goto set;
+ }
+
+ /* Not found. */
+ return -1;
+
+set:
+ result_bound->value = value;
+ result_bound->set = true;
+ return 0;
+
+lazy:
+ result_bound->lazy = true;
+ return 0;
+}
+
+static
+enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params)