diff --git a/core/core.services.yml b/core/core.services.yml
index a32dd04e07667f91815de458a1b00ebe41bb1d26..c3e6fee3391f269b5f4c63e81f1aea654e968fde 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -585,7 +585,7 @@ services:
     arguments: ['@module_handler']
   date:
     class: Drupal\Core\Datetime\Date
-    arguments: ['@entity.manager', '@language_manager']
+    arguments: ['@entity.manager', '@language_manager', '@string_translation']
   feed.bridge.reader:
     class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
     calls:
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 9973074f6a641e15299cf65c814b9d6c72bd7351..12ccffd8b636fbd46178d95301293fdaacbeaeb7 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -897,39 +897,11 @@ function format_xml_elements($array) {
  *
  * @see t()
  * @see format_string()
+ *
+ * @deprecated as of Drupal 8.0. Use \Drupal::translation()->formatPlural()
  */
 function format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
-  $args['@count'] = $count;
-  // Join both forms to search a translation.
-  $tranlatable_string = implode(LOCALE_PLURAL_DELIMITER, array($singular, $plural));
-  // Translate as usual.
-  $translated_strings = t($tranlatable_string, $args, $options);
-  // Split joined translation strings into array.
-  $translated_array = explode(LOCALE_PLURAL_DELIMITER, $translated_strings);
-
-  if ($count == 1) {
-    return $translated_array[0];
-  }
-
-  // Get the plural index through the gettext formula.
-  // @todo implement static variable to minimize function_exists() usage.
-  $index = (function_exists('locale_get_plural')) ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;
-  if ($index == 0) {
-    // Singular form.
-    return $translated_array[0];
-  }
-  else {
-    if (isset($translated_array[$index])) {
-      // N-th plural form.
-      return $translated_array[$index];
-    }
-    else {
-      // If the index cannot be computed or there's no translation, use
-      // the second plural form as a fallback (which allows for most flexiblity
-      // with the replaceable @count value).
-      return $translated_array[1];
-    }
-  }
+  return \Drupal::translation()->formatPlural($count, $singular, $plural, $args, $options);
 }
 
 /**
@@ -1007,31 +979,11 @@ function format_size($size, $langcode = NULL) {
  *
  * @return
  *   A translated string representation of the interval.
+ *
+ * @deprecated as of Drupal 8.0. Use \Drupal::service('date')->formatInterval().
  */
 function format_interval($interval, $granularity = 2, $langcode = NULL) {
-  $units = array(
-    '1 year|@count years' => 31536000,
-    '1 month|@count months' => 2592000,
-    '1 week|@count weeks' => 604800,
-    '1 day|@count days' => 86400,
-    '1 hour|@count hours' => 3600,
-    '1 min|@count min' => 60,
-    '1 sec|@count sec' => 1
-  );
-  $output = '';
-  foreach ($units as $key => $value) {
-    $key = explode('|', $key);
-    if ($interval >= $value) {
-      $output .= ($output ? ' ' : '') . format_plural(floor($interval / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
-      $interval %= $value;
-      $granularity--;
-    }
-
-    if ($granularity == 0) {
-      break;
-    }
-  }
-  return $output ? $output : t('0 sec', array(), array('langcode' => $langcode));
+  return \Drupal::service('date')->formatInterval($interval, $granularity, $langcode);
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Datetime/Date.php b/core/lib/Drupal/Core/Datetime/Date.php
index 08631834caa865f5d6bdc7a0527cfe565f092cc4..0510fa49d2f196775b94132fd85f55dc6e9111f8 100644
--- a/core/lib/Drupal/Core/Datetime/Date.php
+++ b/core/lib/Drupal/Core/Datetime/Date.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
+use Drupal\Core\StringTranslation\TranslationInterface;
 
 /**
  * Provides a service to handler various date related functionality.
@@ -42,6 +43,25 @@ class Date {
   protected $country = NULL;
   protected $dateFormats = array();
 
+  /**
+   * Contains the different date interval units.
+   *
+   * This array is keyed by strings representing the unit (e.g.
+   * '1 year|@count years') and with the amount of values of the unit in
+   * seconds.
+   *
+   * @var array
+   */
+  protected $units = array(
+    '1 year|@count years' => 31536000,
+    '1 month|@count months' => 2592000,
+    '1 week|@count weeks' => 604800,
+    '1 day|@count days' => 86400,
+    '1 hour|@count hours' => 3600,
+    '1 min|@count min' => 60,
+    '1 sec|@count sec' => 1,
+  );
+
   /**
    * Constructs a Date object.
    *
@@ -49,10 +69,13 @@ class Date {
    *   The entity manager.
    * @param \Drupal\Core\Language\LanguageManager $language_manager
    *   The language manager.
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
+   *   The string translation.
    */
-  public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager) {
+  public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager, TranslationInterface $translation) {
     $this->dateFormatStorage = $entity_manager->getStorageController('date_format');
     $this->languageManager = $language_manager;
+    $this->stringTranslation = $translation;
   }
 
   /**
@@ -127,6 +150,47 @@ public function format($timestamp, $type = 'medium', $format = '', $timezone = N
     return Xss::filter($date->format($format, $settings));
   }
 
+  /**
+   * Formats a time interval with the requested granularity.
+   *
+   * @param int $interval
+   *   The length of the interval in seconds.
+   * @param int $granularity
+   *   (optional) How many different units to display in the string (2 by
+   *   default).
+   * @param string $langcode
+   *   (optional) Language code to translate to a language other than what is
+   *   used to display the page. Defaults to NULL.
+   *
+   * @return string
+   *   A translated string representation of the interval.
+   */
+  public function formatInterval($interval, $granularity = 2, $langcode = NULL) {
+    $output = '';
+    foreach ($this->units as $key => $value) {
+      $key = explode('|', $key);
+      if ($interval >= $value) {
+        $output .= ($output ? ' ' : '') . $this->stringTranslation->formatPlural(floor($interval / $value), $key[0], $key[1], array(), array('langcode' => $langcode));
+        $interval %= $value;
+        $granularity--;
+      }
+
+      if ($granularity == 0) {
+        break;
+      }
+    }
+    return $output ? $output : $this->t('0 sec', array(), array('langcode' => $langcode));
+  }
+
+  /**
+   * Translates a string to the current language or to a given language.
+   *
+   * See the t() documentation for details.
+   */
+  protected function t($string, array $args = array(), array $options = array()) {
+    return $this->stringTranslation->translate($string, $args, $options);
+  }
+
   /**
    * Loads the given format pattern for the given langcode.
    *
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
index f0d7b45607c7a9e07de2ad2c3186026ae15ad8d6..c3610ff520f01dfa8dcbcd9434b9ec8c86e38d29 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationInterface.php
@@ -31,4 +31,53 @@ interface TranslationInterface {
    */
   public function translate($string, array $args = array(), array $options = array());
 
+  /**
+   * Formats a string containing a count of items.
+   *
+   * This function ensures that the string is pluralized correctly. Since t() is
+   * called by this function, make sure not to pass already-localized strings to
+   * it.
+   *
+   * For example:
+   * @code
+   *   $output = $string_translation->formatPlural($node->comment_count, '1 comment', '@count comments');
+   * @endcode
+   *
+   * Example with additional replacements:
+   * @code
+   *   $output = $string_translation->formatPlural($update_count,
+   *     'Changed the content type of 1 post from %old-type to %new-type.',
+   *     'Changed the content type of @count posts from %old-type to %new-type.',
+   *     array('%old-type' => $info->old_type, '%new-type' => $info->new_type));
+   * @endcode
+   *
+   * @param int $count
+   *   The item count to display.
+   * @param string $singular
+   *   The string for the singular case. Make sure it is clear this is singular,
+   *   to ease translation (e.g. use "1 new comment" instead of "1 new"). Do not
+   *   use @count in the singular string.
+   * @param string $plural
+   *   The string for the plural case. Make sure it is clear this is plural, to
+   *   ease translation. Use @count in place of the item count, as in
+   *   "@count new comments".
+   * @param array $args
+   *   An associative array of replacements to make after translation. Instances
+   *   of any key in this array are replaced with the corresponding value.
+   *   Based on the first character of the key, the value is escaped and/or
+   *   themed. See format_string(). Note that you do not need to include @count
+   *   in this array; this replacement is done automatically for the plural case.
+   * @param array $options
+   *   An associative array of additional options. See t() for allowed keys.
+   *
+   * @return string
+   *   A translated string.
+   *
+   * @see self::translate
+   * @see \Drupal\Component\Utility\String
+   * @see t()
+   * @see format_string()
+   */
+  public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array());
+
 }
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
index 8fa2fc7f7d13e7b3164349ac28dbb59f61494266..191ece45a91223f00eebc7a6bb3ce1831da53ecd 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
@@ -126,6 +126,43 @@ public function translate($string, array $args = array(), array $options = array
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function formatPlural($count, $singular, $plural, array $args = array(), array $options = array()) {
+    $args['@count'] = $count;
+    // Join both forms to search a translation.
+    $translatable_string = implode(LOCALE_PLURAL_DELIMITER, array($singular, $plural));
+    // Translate as usual.
+    $translated_strings = $this->translate($translatable_string, $args, $options);
+    // Split joined translation strings into array.
+    $translated_array = explode(LOCALE_PLURAL_DELIMITER, $translated_strings);
+
+    if ($count == 1) {
+      return $translated_array[0];
+    }
+
+    // Get the plural index through the gettext formula.
+    // @todo implement static variable to minimize function_exists() usage.
+    $index = (function_exists('locale_get_plural')) ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;
+    if ($index == 0) {
+      // Singular form.
+      return $translated_array[0];
+    }
+    else {
+      if (isset($translated_array[$index])) {
+        // N-th plural form.
+        return $translated_array[$index];
+      }
+      else {
+        // If the index cannot be computed or there's no translation, use
+        // the second plural form as a fallback (which allows for most flexiblity
+        // with the replaceable @count value).
+        return $translated_array[1];
+      }
+    }
+  }
+
   /**
    * Sets the default langcode.
    *
diff --git a/core/tests/Drupal/Tests/Core/Datetime/DateTest.php b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..32d2103d527bbd483cf278db4f07d6fec1a70ddd
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Datetime/DateTest.php
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Datetime\DateTest.
+ */
+
+namespace Drupal\Tests\Core\Datetime;
+
+use Drupal\Core\Datetime\Date;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the date service.
+ *
+ * @group Drupal
+ *
+ * @see \Drupal\Core\Datetime\Date
+ */
+class DateTest extends UnitTestCase {
+
+  /**
+   * The mocked entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityManager;
+
+  /**
+   * The mocked language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManager|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $languageManager;
+
+  /**
+   * The mocked string translation.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $stringTranslation;
+
+  /**
+   * The tested date service class.
+   *
+   * @var \Drupal\Core\Datetime\Date
+   */
+  protected $date;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Date service test.',
+      'description' => 'Tests the date service.',
+      'group' => 'System'
+    );
+  }
+
+  protected function setUp() {
+    $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
+    $this->languageManager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $this->stringTranslation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
+
+    $this->date = new Date($this->entityManager, $this->languageManager, $this->stringTranslation);
+  }
+
+  /**
+   * Tests the formatPlugin method.
+   *
+   * @dataProvider providerTestFormatInterval
+   *
+   * @see \Drupal\Core\Datetime\Date::formatInterval()
+   */
+  public function testFormatInterval($interval, $granularity, $expected, $langcode = NULL) {
+    // Mocks a simple formatPlural implementation.
+    $this->stringTranslation->expects($this->any())
+      ->method('formatPlural')
+      ->with($this->anything(), $this->anything(), $this->anything(), array(), array('langcode' => $langcode))
+      ->will($this->returnCallback(function($count, $one, $multiple) {
+        return $count == 1 ? $one : str_replace('@count', $count, $multiple);
+      }));
+
+    // Check if the granularity is specified.
+    if ($granularity) {
+      $result = $this->date->formatInterval($interval, $granularity, $langcode);
+    }
+    else {
+      $result = $this->date->formatInterval($interval);
+    }
+
+    $this->assertEquals($expected, $result);
+  }
+
+  /**
+   * Provides some test data for the format interval test.
+   */
+  public function providerTestFormatInterval() {
+    $data = array(
+      // Checks for basic seconds.
+      array(1, 1, '1 sec'),
+      array(1, 2, '1 sec'),
+      array(2, 1, '2 sec'),
+      array(2, 2, '2 sec'),
+      // Checks for minutes with seconds.
+      array(61, 1, '1 min'),
+      array(61, 2, '1 min 1 sec'),
+      array(62, 2, '1 min 2 sec'),
+      array(121, 1, '2 min'),
+      array(121, 2, '2 min 1 sec'),
+      // Check for hours with minutes and seconds.
+      array(3601, 1, '1 hour'),
+      array(3601, 2, '1 hour 1 sec'),
+      // Check for higher units.
+      array(86401, 1, '1 day'),
+      array(604800, 1, '1 week'),
+      array(2592000 * 2, 1, '2 months'),
+      array(31536000 * 2, 1, '2 years'),
+      // Check for a complicated one with months weeks and days.
+      array(2592000 * 2 + 604800 * 3 + 86400 * 4, 3, '2 months 3 weeks 4 days'),
+      // Check for the langcode.
+      array(61, 1, '1 min', 'xxx-lolspeak'),
+      // Check with an unspecified granularity.
+      array(61, NULL, '1 min 1 sec'),
+    );
+
+    return $data;
+  }
+
+  /**
+   * Tests the formatInterval method for 0 second.
+   */
+  public function testFormatIntervalZeroSecond() {
+    $this->stringTranslation->expects($this->once())
+      ->method('translate')
+      ->with('0 sec', array(), array('langcode' => 'xxx-lolspeak'))
+      ->will($this->returnValue('0 sec'));
+
+    $result = $this->date->formatInterval(0, 1, 'xxx-lolspeak');
+
+    $this->assertEquals('0 sec', $result);
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/StringTranslation/TranslationManagerTest.php b/core/tests/Drupal/Tests/Core/StringTranslation/TranslationManagerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f75a5fa7272870f9526e8cd0ad01361143d5eaa0
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/StringTranslation/TranslationManagerTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\StringTranslation\TranslationManagerTest.
+ */
+
+namespace Drupal\Tests\Core\StringTranslation {
+
+use Drupal\Core\StringTranslation\TranslationManager;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the translation manager.
+ *
+ * @see \Drupal\Core\StringTranslation\TranslationManager
+ */
+class TranslationManagerTest extends UnitTestCase {
+
+  /**
+   * The tested translation manager.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationManager
+   */
+  protected $translationManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Translation manager',
+      'description' => 'Tests the translation manager.',
+      'group' => 'Translation',
+    );
+  }
+
+  protected function setUp() {
+    $this->translationManager = new TestTranslationManager();
+  }
+
+  /**
+   * Provides some test data for formatPlural()
+   * @return array
+   */
+  public function providerTestFormatPlural() {
+    return array(
+      array(1, 'Singular', '@count plural', array(), array(), 'Singular'),
+      array(2, 'Singular', '@count plural', array(), array(), '2 plural'),
+      // @todo support locale_get_plural
+      array(2, 'Singular', '@count plural @arg', array('@arg' => 3), array(), '2 plural 3'),
+    );
+  }
+
+  /**
+   * @dataProvider providerTestFormatPlural
+   */
+  public function testFormatPlural($count, $singular, $plural, array $args = array(), array $options = array(), $expected) {
+    $translator = $this->getMock('\Drupal\Core\StringTranslation\Translator\TranslatorInterface');
+    $translator->expects($this->once())
+      ->method('getStringTranslation')
+      ->will($this->returnCallback(function ($langcode, $string) {
+        return $string;
+      }));
+    $this->translationManager->addTranslator($translator);
+    $result = $this->translationManager->formatPlural($count, $singular, $plural, $args, $options);
+    $this->assertEquals($expected, $result);
+  }
+
+}
+
+class TestTranslationManager extends TranslationManager {
+
+  public function __construct() {
+  }
+
+}
+
+}
+
+namespace {
+  if (!defined('LOCALE_PLURAL_DELIMITER')) {
+    define('LOCALE_PLURAL_DELIMITER', "\03");
+  }
+}