diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -342,6 +342,7 @@
   'function' =>
   array(
     'Futures' => 'future/functions.php',
+    '_phabricator_date_format' => 'utils/viewutils.php',
     '_qsprintf_check_scalar_type' => 'xsprintf/qsprintf.php',
     '_qsprintf_check_type' => 'xsprintf/qsprintf.php',
     'array_fuse' => 'utils/utils.php',
@@ -374,6 +375,11 @@
     'msort' => 'utils/utils.php',
     'newv' => 'utils/utils.php',
     'nonempty' => 'utils/utils.php',
+    'phabricator_format_bytes' => 'utils/viewutils.php',
+    'phabricator_format_relative_time' => 'utils/viewutils.php',
+    'phabricator_format_relative_time_detailed' => 'utils/viewutils.php',
+    'phabricator_format_units_generic' => 'utils/viewutils.php',
+    'phabricator_parse_bytes' => 'utils/viewutils.php',
     'phlog' => 'error/phlog.php',
     'pht' => 'internationalization/pht.php',
     'phutil_censor_credentials' => 'utils/utils.php',
diff --git a/src/utils/viewutils.php b/src/utils/viewutils.php
new file mode 100644
--- /dev/null
+++ b/src/utils/viewutils.php
@@ -0,0 +1,171 @@
+<?php
+
+function _phabricator_date_format($epoch) {
+  $now = time();
+  $shift = 30 * 24 * 60 * 60;
+  if ($epoch < $now + $shift && $epoch > $now - $shift) {
+    $format = pht('D, M j');
+  } else {
+    $format = pht('M j Y');
+  }
+  return $format;
+}
+
+function phabricator_format_relative_time($duration) {
+  return phabricator_format_units_generic(
+    $duration,
+    array(60, 60, 24, 7),
+    array('s', 'm', 'h', 'd', 'w'),
+    $precision = 0);
+}
+
+/**
+ * Format a relative time (duration) into weeks, days, hours, minutes,
+ * seconds, but unlike phabricator_format_relative_time, does so for more than
+ * just the largest unit.
+ *
+ * @param int Duration in seconds.
+ * @param int Levels to render - will render the three highest levels, ie:
+ *            5 h, 37 m, 1 s
+ * @return string Human-readable description.
+ */
+function phabricator_format_relative_time_detailed($duration, $levels = 2) {
+  if ($duration == 0) {
+    return 'now';
+  }
+  $levels = max(1, min($levels, 5));
+  $remainder = 0;
+
+  $is_negative = false;
+  if ($duration < 0) {
+    $is_negative = true;
+    $duration = abs($duration);
+  }
+
+  $this_level = 1;
+  $detailed_relative_time = phabricator_format_units_generic(
+    $duration,
+    array(60, 60, 24, 7),
+    array('s', 'm', 'h', 'd', 'w'),
+    $precision = 0,
+    $remainder);
+  $duration = $remainder;
+
+  while ($remainder > 0 && $this_level < $levels) {
+    $detailed_relative_time .= ', '.phabricator_format_units_generic(
+      $duration,
+      array(60, 60, 24, 7),
+      array('s', 'm', 'h', 'd', 'w'),
+      $precision = 0,
+      $remainder);
+    $duration = $remainder;
+    $this_level++;
+  };
+
+  if ($is_negative) {
+    $detailed_relative_time .= ' ago';
+  }
+
+  return $detailed_relative_time;
+}
+
+/**
+ * Format a byte count for human consumption, e.g. "10MB" instead of
+ * "10000000".
+ *
+ * @param int Number of bytes.
+ * @return string Human-readable description.
+ */
+function phabricator_format_bytes($bytes) {
+  return phabricator_format_units_generic(
+    $bytes,
+    // NOTE: Using the SI version of these units rather than the 1024 version.
+    array(1000, 1000, 1000, 1000, 1000),
+    array('B', 'KB', 'MB', 'GB', 'TB', 'PB'),
+    $precision = 0);
+}
+
+
+/**
+ * Parse a human-readable byte description (like "6MB") into an integer.
+ *
+ * @param string  Human-readable description.
+ * @return int    Number of represented bytes.
+ */
+function phabricator_parse_bytes($input) {
+  $bytes = trim($input);
+  if (!strlen($bytes)) {
+    return null;
+  }
+
+  // NOTE: Assumes US-centric numeral notation.
+  $bytes = preg_replace('/[ ,]/', '', $bytes);
+
+  $matches = null;
+  if (!preg_match('/^(?:\d+(?:[.]\d+)?)([kmgtp]?)b?$/i', $bytes, $matches)) {
+    throw new Exception("Unable to parse byte size '{$input}'!");
+  }
+
+  $scale = array(
+    'k' => 1000,
+    'm' => 1000 * 1000,
+    'g' => 1000 * 1000 * 1000,
+    't' => 1000 * 1000 * 1000 * 1000,
+    'p' => 1000 * 1000 * 1000 * 1000 * 1000,
+  );
+
+  $bytes = (float)$bytes;
+  if ($matches[1]) {
+    $bytes *= $scale[strtolower($matches[1])];
+  }
+
+  return (int)$bytes;
+}
+
+
+function phabricator_format_units_generic(
+  $n,
+  array $scales,
+  array $labels,
+  $precision  = 0,
+  &$remainder = null) {
+
+  $is_negative = false;
+  if ($n < 0) {
+    $is_negative = true;
+    $n = abs($n);
+  }
+
+  $remainder = 0;
+  $accum = 1;
+
+  $scale = array_shift($scales);
+  $label = array_shift($labels);
+  while ($n >= $scale && count($labels)) {
+    $remainder += ($n % $scale) * $accum;
+    $n /= $scale;
+    $accum *= $scale;
+    $label = array_shift($labels);
+    if (!count($scales)) {
+      break;
+    }
+    $scale = array_shift($scales);
+  }
+
+  if ($is_negative) {
+    $n = -$n;
+    $remainder = -$remainder;
+  }
+
+  if ($precision) {
+    $num_string = number_format($n, $precision);
+  } else {
+    $num_string = (int)floor($n);
+  }
+
+  if ($label) {
+    $num_string .= ' '.$label;
+  }
+
+  return $num_string;
+}