--- old/usr/src/cmd/stat/kstat/kstat.c	Thu Jan 28 18:01:11 2016
+++ new/usr/src/cmd/stat/kstat/kstat.c	Thu Jan 28 18:01:11 2016
@@ -24,6 +24,7 @@
  * Copyright (c) 2013 David Hoeppner. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2016 Garrett D'Amore
  */
 
 /*
@@ -39,6 +40,12 @@
  *	-C	similar to the -p option but value is separated by a colon
  *	-h	display help
  *	-j	json format
+ *	-H b	display hrtime as seconds since boot
+ *	-H d	display hrtime as date
+ *	-H u	display hrtime as UNIX seconds (since epoch)
+ *	-H I	display hrtime as ISO-8601 local time
+ *	-H Z	display hrtime as ISO-8601 UTC
+ *	-H n	display hrtime as nanoseconds (since epoch)
  */
 
 #include <assert.h>
@@ -68,6 +75,7 @@
 int	caught_cont = 0;	/* Have caught a SIGCONT */
 
 static uint_t	g_timestamp_fmt = NODATE;
+static uint_t	g_hrtime_fmt = KS_HRFMT_DEFAULT;
 
 /* Helper flag - header was printed already? */
 static boolean_t g_headerflg;
@@ -87,6 +95,8 @@
 static list_t	instances_list;
 static list_t	selector_list;
 
+static hrtime_t	hrtime_origin;
+
 int
 main(int argc, char **argv)
 {
@@ -124,7 +134,7 @@
 	/*
 	 * Parse named command line arguments.
 	 */
-	while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF)
+	while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:H:")) != EOF)
 		switch (c) {
 		case 'h':
 		case '?':
@@ -147,6 +157,9 @@
 			g_pflg = B_TRUE;
 			break;
 		case 'T':
+			if (strlen(optarg) != 1) {
+				errflg = B_TRUE;
+			}
 			switch (*optarg) {
 			case 'd':
 				g_timestamp_fmt = DDATE;
@@ -182,6 +195,25 @@
 			g_ks_class.pstr =
 			    (char *)ks_safe_strdup(optarg);
 			break;
+		case 'H':
+			switch (*optarg) {
+			case 'o':
+			case 'b':
+			case 'n':
+			case 'I':
+			case 'Z':
+			case 'd':
+			case 'u':
+				if (strlen(optarg) != 1) {
+					errflg = B_TRUE;
+				}
+				g_hrtime_fmt = *optarg;
+				break;
+			default:
+				errflg = B_TRUE;
+				break;
+			}
+			break;
 		default:
 			errflg = B_TRUE;
 			break;
@@ -193,6 +225,23 @@
 		errflg = B_TRUE;
 	}
 
+	switch (g_hrtime_fmt) {
+	case KS_HRFMT_DEFAULT:
+	case KS_HRFMT_BOOT:
+		break;
+	default: {
+		struct timespec ts;
+		if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
+			perror("clock_gettime(CLOCK_REALTIME)");
+			exit(3);
+		}
+		hrtime_origin = ts.tv_sec;
+		hrtime_origin *= 1000000000;
+		hrtime_origin += ts.tv_nsec;
+		hrtime_origin -= gethrtime();
+	}
+	}
+
 	if (errflg) {
 		usage();
 		exit(2);
@@ -352,10 +401,10 @@
 {
 	(void) fprintf(stderr, gettext(
 	    "Usage:\n"
-	    "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
+	    "kstat [ -Cjlpq ] [ -T d|u ] [ -H d|n|u|I|Z ] [ -c class ]\n"
 	    "      [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
 	    "      [ interval [ count ] ]\n"
-	    "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
+	    "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ] [ -H d|n|u|I|Z ]\n"
 	    "      [ module[:instance[:name[:statistic]]] ... ]\n"
 	    "      [ interval [ count ] ]\n"));
 }
@@ -708,6 +757,10 @@
 static void
 ks_value_print(ks_nvpair_t *nvpair)
 {
+	char dstr[64];
+	char zstr[8];
+	time_t t;
+
 	switch (nvpair->data_type) {
 	case KSTAT_DATA_CHAR:
 		(void) fprintf(stdout, "%s", nvpair->value.c);
@@ -727,12 +780,53 @@
 	case KSTAT_DATA_STRING:
 		(void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
 		break;
-	case KSTAT_DATA_HRTIME:
-		if (nvpair->value.ui64 == 0)
-			(void) fprintf(stdout, "0");
-		else
+	case KSTAT_DATA_TIME:
+		switch (g_hrtime_fmt) {
+		case KS_HRFMT_UNIX:
 			(void) fprintf(stdout, "%.9f",
-			    nvpair->value.ui64 / 1000000000.0);
+			    (nvpair->value.t + hrtime_origin) / 1000000000.0);
+			break;
+		case KS_HRFMT_NANO:
+			(void) fprintf(stdout, "%llu",
+			    (nvpair->value.t + hrtime_origin));
+			break;
+		case KS_HRFMT_DATE:
+			t = (time_t)
+			    ((nvpair->value.t + hrtime_origin) / 1000000000);
+			(void) strftime(dstr,
+			    sizeof (dstr), "%+", localtime(&t));
+			(void) fprintf(stdout, "%s", dstr);
+			break;
+		case KS_HRFMT_ZISO:
+			t = (time_t)
+			    ((nvpair->value.t + hrtime_origin) / 1000000000);
+			(void) strftime(dstr, sizeof (dstr), "%FT%T",
+			    gmtime(&t));
+			(void) fprintf(stdout, "%s.%06uZ", dstr,
+			    (unsigned)(nvpair->value.t % 1000000000)/1000);
+			break;
+		case KS_HRFMT_ISO:
+			t = (time_t)
+			    ((nvpair->value.t + hrtime_origin) / 1000000000);
+			(void) strftime(dstr, sizeof (dstr), "%FT%T",
+			    localtime(&t));
+			(void) strftime(zstr, sizeof (zstr), "%z",
+			    localtime(&t));
+			(void) fprintf(stdout, "%s.%06u%s", dstr,
+			    (unsigned)(nvpair->value.t % 1000000000)/1000,
+			    zstr);
+			break;
+		case KS_HRFMT_DEFAULT:
+		case KS_HRFMT_BOOT:
+			if (nvpair->value.ui64 == 0)
+				(void) fprintf(stdout, "0");
+			else
+				(void) fprintf(stdout, "%.9f",
+				    nvpair->value.ui64 / 1000000000.0);
+			break;
+		default:
+			abort();
+		}
 		break;
 	default:
 		assert(B_FALSE);
@@ -798,6 +892,18 @@
 		(void) putchar('\"');
 		ks_value_print(nvpair);
 		(void) putchar('\"');
+	} else if (nvpair->data_type == KSTAT_DATA_TIME) {
+		switch (g_hrtime_fmt) {
+		case KS_HRFMT_ISO:
+		case KS_HRFMT_ZISO:
+		case KS_HRFMT_DATE:
+			(void) putchar('\"');
+			ks_value_print(nvpair);
+			(void) putchar('\"');
+			break;
+		default:
+			ks_value_print(nvpair);
+		}
 	} else {
 		ks_value_print(nvpair);
 	}
@@ -1388,24 +1494,13 @@
 	for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
 		switch (knp->data_type) {
 		case KSTAT_DATA_CHAR:
-			nvpair_insert(ksi, knp->name,
-			    (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
-			break;
 		case KSTAT_DATA_INT32:
-			nvpair_insert(ksi, knp->name,
-			    (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
-			break;
 		case KSTAT_DATA_UINT32:
-			nvpair_insert(ksi, knp->name,
-			    (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
-			break;
 		case KSTAT_DATA_INT64:
-			nvpair_insert(ksi, knp->name,
-			    (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
-			break;
 		case KSTAT_DATA_UINT64:
+		case KSTAT_DATA_TIME:
 			nvpair_insert(ksi, knp->name,
-			    (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
+			    (ks_value_t *)&knp->value, knp->data_type);
 			break;
 		case KSTAT_DATA_STRING:
 			SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
@@ -1438,11 +1533,11 @@
 	SAVE_UINT64(ksi, ksio, nwritten);
 	SAVE_UINT32(ksi, ksio, reads);
 	SAVE_UINT32(ksi, ksio, writes);
-	SAVE_HRTIME(ksi, ksio, wtime);
-	SAVE_HRTIME(ksi, ksio, wlentime);
+	SAVE_UINT64(ksi, ksio, wtime);
+	SAVE_UINT64(ksi, ksio, wlentime);
 	SAVE_HRTIME(ksi, ksio, wlastupdate);
-	SAVE_HRTIME(ksi, ksio, rtime);
-	SAVE_HRTIME(ksi, ksio, rlentime);
+	SAVE_UINT64(ksi, ksio, rtime);
+	SAVE_UINT64(ksi, ksio, rlentime);
 	SAVE_HRTIME(ksi, ksio, rlastupdate);
 	SAVE_UINT32(ksi, ksio, wcnt);
 	SAVE_UINT32(ksi, ksio, rcnt);
@@ -1455,9 +1550,9 @@
 
 	SAVE_STRING(ksi, ktimer, name);
 	SAVE_UINT64(ksi, ktimer, num_events);
-	SAVE_HRTIME(ksi, ktimer, elapsed_time);
-	SAVE_HRTIME(ksi, ktimer, min_time);
-	SAVE_HRTIME(ksi, ktimer, max_time);
+	SAVE_UINT64(ksi, ktimer, elapsed_time);
+	SAVE_UINT64(ksi, ktimer, min_time);
+	SAVE_UINT64(ksi, ktimer, max_time);
 	SAVE_HRTIME(ksi, ktimer, start_time);
 	SAVE_HRTIME(ksi, ktimer, stop_time);
 }
