text: #include <stdlib.h>
  #include <string.h>
  #include <sys/time.h>
  #include <linux/time64.h>
  #include <time.h>
  #include <errno.h>
  #include <inttypes.h>
  
  #include "perf.h"
  #include "debug.h"
  #include "time-utils.h"
  
  int parse_nsec_time(const char *str, u64 *ptime)
  {
  	u64 time_sec, time_nsec;
  	char *end;
  
  	time_sec = strtoul(str, &end, 10);
  	if (*end != '.' && *end != '\0')
  		return -1;
  
  	if (*end == '.') {
  		int i;
  		char nsec_buf[10];
  
  		if (strlen(++end) > 9)
  			return -1;
  
  		strncpy(nsec_buf, end, 9);
  		nsec_buf[9] = '\0';
  
  		/* make it nsec precision */
  		for (i = strlen(nsec_buf); i < 9; i++)
  			nsec_buf[i] = '0';
  
  		time_nsec = strtoul(nsec_buf, &end, 10);
  		if (*end != '\0')
  			return -1;
  	} else
  		time_nsec = 0;
  
  	*ptime = time_sec * NSEC_PER_SEC + time_nsec;
  	return 0;
  }
  
  static int parse_timestr_sec_nsec(struct perf_time_interval *ptime,
  				  char *start_str, char *end_str)
  {
  	if (start_str && (*start_str != '\0') &&
  	    (parse_nsec_time(start_str, &ptime->start) != 0)) {
  		return -1;
  	}
  
  	if (end_str && (*end_str != '\0') &&
  	    (parse_nsec_time(end_str, &ptime->end) != 0)) {
  		return -1;
  	}
  
  	return 0;
  }
  
  int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
  {
  	char *start_str, *end_str;
  	char *d, *str;
  	int rc = 0;
  
  	if (ostr == NULL || *ostr == '\0')
  		return 0;
  
  	/* copy original string because we need to modify it */
  	str = strdup(ostr);
  	if (str == NULL)
  		return -ENOMEM;
  
  	ptime->start = 0;
  	ptime->end = 0;
  
  	/* str has the format: <start>,<stop>
  	 * variations: <start>,
  	 *             ,<stop>
  	 *             ,
  	 */
  	start_str = str;
  	d = strchr(start_str, ',');
  	if (d) {
  		*d = '\0';
  		++d;
  	}
  	end_str = d;
  
  	rc = parse_timestr_sec_nsec(ptime, start_str, end_str);
  
  	free(str);
  
  	/* make sure end time is after start time if it was given */
  	if (rc == 0 && ptime->end && ptime->end < ptime->start)
  		return -EINVAL;
  
  	pr_debug("start time %" PRIu64 ", ", ptime->start);
  	pr_debug("end time %" PRIu64 "\n", ptime->end);
  
  	return rc;
  }
  
  bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
  {
  	/* if time is not set don't drop sample */
  	if (timestamp == 0)
  		return false;
  
  	/* otherwise compare sample time to time window */
  	if ((ptime->start && timestamp < ptime->start) ||
  	    (ptime->end && timestamp > ptime->end)) {
  		return true;
  	}
  
  	return false;
  }
  