From cfd9123d85f6434ca9a65501ffcdb06b50ed4b63 Mon Sep 17 00:00:00 2001
From: Morris Jette <jette@schedmd.com>
Date: Tue, 7 Jun 2011 21:45:31 -0700
Subject: [PATCH] squeue: contex-sensitive time printing

Especially on long listings of jobs or records, there is very little variation in
adjacent entries, causing repetition of output which can make it difficult to
quickly see changes.

This also makes it easier to spot outliers: as in the example a the end of
April below, where a user had set a BeginTime of about 1 month in advance:

JOBID  USER     ACCOUNT               NAME     REASON NODES  TIMELIMIT   START_TIME
54936  teyssier    s201     cut_largemodes   Priority    16 1-00:00:00     18:37:30
33544  jgomez       s89        Rh_12x12-4L   Priority     8 1-00:00:00     18:39:02
40798  jgomez       s89        Rh_8x8x8_D3   Priority    20   23:59:00     18:40:29
31994  xyy         s241     new-3g5u-lipid   Priority    22 1-00:00:00     18:40:29
32072  gstarek     s241        alpha_vs_dp   Priority    22 1-00:00:00     18:40:29
32078  gstarek     s241         control_vs   Priority    22 1-00:00:00     18:40:29
31699  jgomez       s89            CHP_120  BeginTime    20 1-00:00:00 29 May 16:43
22121  guerard     s263          an18QM370 Dependency     8    2:00:00          N/A

The patch introduces a context-sensitive time format which is
 * disabled by default
 * enabled via SLURM_TIME_FORMAT environment variable,
 * prints 24-hour clock based time relative to "now",
 * takes up at most 12 characters (i.e. 1/2 character per hour).

The following compares the formats for a range of settings:

  1) SLURM_TIME_FORMAT=standard
  now                      2011-06-06T12:57:22
  yesterday 2pm            2011-06-05T14:00:00
  19 jan 1904 3:15         1904-01-19T03:15:00
  -2 days 4:15pm           2011-06-04T16:15:00
  tomorrow                 2011-06-07T12:57:22
  +2 days 2:17am           2011-06-08T02:17:00
  +3 days 2:18pm           2011-06-09T14:18:00
  -6 weeks                 2011-04-25T12:57:22
  +3 weeks + 10 days       2011-07-07T12:57:22
  next year                2012-06-06T12:57:22

  2) SLURM_TIME_FORMAT=relative
  now                                 12:57:22
  yesterday 2pm                   Ystday 14:00
  19 jan 1904 3:15                 19 Jan 1904
  -2 days 4:15pm                   4 Jun 16:15
  tomorrow                        Tomorr 12:57
  +2 days 2:17am                     Wed 02:17
  +3 days 2:18pm                     Thu 14:18src/common/parse_time.c
  -6 weeks                        25 Apr 12:57
  +3 weeks + 10 days               7 Jul 12:57
  next year                         6 Jun 2012

  3) SLURM_TIME_FORMAT="%a %T"
  now                             Mon 12:57:22
  yesterday 2pm                   Sun 14:00:00
  19 jan 1904 3:15                Tue 03:15:00
  -2 days 4:15pm                  Sat 16:15:00
  tomorrow                        Tue 12:57:22
  +2 days 2:17am                  Wed 02:17:00
  +3 days 2:18pm                  Thu 14:18:00
04_COSMETICS_context-dependent-timestring.diff Patch by Gerrit Renker, CSCS
---
 src/common/parse_time.c | 91 +++++++++++++++++++++++++++++++++--------
 1 file changed, 74 insertions(+), 17 deletions(-)

diff --git a/src/common/parse_time.c b/src/common/parse_time.c
index 5f12bf1ed04..79a14785c8b 100644
--- a/src/common/parse_time.c
+++ b/src/common/parse_time.c
@@ -534,8 +534,50 @@ int main(int argc, char *argv[])
 #endif
 
 /*
- * slurm_make_time_str - convert time_t to string with a format of
- *	"month/date hour:min:sec" for use in user command output
+ * Smart date for @epoch, relative to current date.
+ * Maximum output length: 12 characters + '\0'
+ *      19 Jan 2003	(distant past or future)
+ *     Ystday 20:13
+ *         12:26:38	(today)
+ *     Tomorr 03:22
+ *        Sat 02:17	(next Saturday)
+ *     18 Jun 13:14	(non-close past or future)
+ *     012345678901
+ * Uses base-10 YYYYddd numbers to compute date distances.
+ */
+static char *_relative_date_fmt(const struct tm *when)
+{
+	static int todays_date;
+	int distance = 1000 * (when->tm_year + 1900) + when->tm_yday;
+
+	if (!todays_date) {
+		time_t now = time(NULL);
+		struct tm tm;
+
+		localtime_r(&now, &tm);
+		todays_date = 1000 * (tm.tm_year + 1900) + tm.tm_yday;
+	}
+
+	distance -= todays_date;
+	if (distance == -1)			/* yesterday */
+		return "Ystday %H:%M";
+	if (distance == 0)			/* same day */
+		return "%H:%M:%S";
+	if (distance == 1)			/* tomorrow */
+		return "Tomorr %H:%M";
+	if (distance < -365 || distance > 365)	/* far distance */
+		return "%-d %b %Y";
+	if (distance < -1 || distance > 6)	/* medium distance */
+		return "%-d %b %H:%M";
+	return "%a %H:%M";			/* near distance */
+}
+
+/*
+ * slurm_make_time_str - convert time_t to formatted string for user output
+ *
+ * The format depends on the environment variable SLURM_TIME_FORMAT, which may
+ * be set to 'standard' (fallback, same as if not set), 'relative' (format is
+ * relative to today's date and optimized for space), or a strftime(3) string.
  *
  * IN time - a time stamp
  * OUT string - pointer user defined buffer
@@ -551,23 +593,38 @@ slurm_make_time_str (time_t *time, char *string, int size)
 	if ((*time == (time_t) 0) || (*time == (time_t) INFINITE)) {
 		snprintf(string, size, "Unknown");
 	} else {
-#ifdef USE_ISO_8601
-		/* Format YYYY-MM-DDTHH:MM:SS, ISO8601 standard format,
-		 * NOTE: This is expected to break Maui, Moab and LSF
-		 * schedulers management of SLURM. */
-		snprintf(string, size,
-			"%4.4u-%2.2u-%2.2uT%2.2u:%2.2u:%2.2u",
-			(time_tm.tm_year + 1900), (time_tm.tm_mon+1),
-			time_tm.tm_mday, time_tm.tm_hour, time_tm.tm_min,
-			time_tm.tm_sec);
+		static char fmt_buf[32];
+		static const char *display_fmt;
+		static bool use_relative_format;
+
+		if (!display_fmt) {
+			char *fmt = getenv("SLURM_TIME_FORMAT");
+
+			if ((!fmt) || (!*fmt) || (!strcmp(fmt, "standard"))) {
+#if defined USE_ISO_8601	/*
+				 * ISO-8601 Standard Format YYYY-MM-DDTHH:MM:SS
+				 * NOTE: This is expected to break Maui, Moab
+				 *       and LSF schedulers management of SLURM.
+				 */
+				display_fmt = "%FT%T";
 #else
-		/* Format MM/DD-HH:MM:SS */
-		snprintf(string, size,
-			"%2.2u/%2.2u-%2.2u:%2.2u:%2.2u",
-			(time_tm.tm_mon+1), time_tm.tm_mday,
-			time_tm.tm_hour, time_tm.tm_min, time_tm.tm_sec);
-
+				/* Format MM/DD-HH:MM:SS */
+				display_fmt = "%m/%d-%T";
 #endif
+			} else if (strcmp(fmt, "relative") == 0) {
+				use_relative_format = true;
+			} else if ((strchr(fmt, '%')  == NULL) ||
+				   (strlen(fmt) >= sizeof(fmt_buf))) {
+				error("invalid SLURM_TIME_FORMAT = '%s'", fmt);
+			} else {
+				strncpy(fmt_buf, fmt, sizeof(fmt_buf));
+				display_fmt = fmt_buf;
+			}
+		}
+		if (use_relative_format)
+			display_fmt = _relative_date_fmt(&time_tm);
+
+		strftime(string, size, display_fmt, &time_tm);
 	}
 }
 
-- 
GitLab