diff --git a/core/modules/system/lib/Drupal/system/Controller/TimezoneController.php b/core/modules/system/lib/Drupal/system/Controller/TimezoneController.php
new file mode 100644
index 0000000..e1a108e
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Controller/TimezoneController.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @file
+ * System timezone controller.
+ *
+ * Provides a callback for finding out a timezone name.
+ */
+
+namespace Drupal\system;
+
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * Controller for system timezone.
+ */
+class TimezoneController {
+  /**
+   * Menu callback: Retrieve a JSON object containing a time zone name given a
+   * timezone abbreviation.
+   */
+  public function getTimezone($abbreviation = '', $offset = -1, $is_daylight_saving_time = NULL) {
+    // An abbreviation of "0" passed in the callback arguments should be
+    // interpreted as the empty string.
+    $abbreviation = $abbreviation ? $abbreviation : '';
+    $timezone = timezone_name_from_abbr($abbreviation, intval($offset), $is_daylight_saving_time);
+    return new JsonResponse($timezone);
+  }
+}
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 0d472e5..2bfa3ed 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -640,13 +640,6 @@ function system_menu() {
     'file path' => 'core/includes',
     'file' => 'form.inc',
   );
-  $items['system/timezone'] = array(
-    'title' => 'Time zone',
-    'page callback' => 'system_timezone',
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-    'file' => 'system.admin.inc',
-  );
   $items['admin'] = array(
     'title' => 'Administration',
     'access arguments' => array('access administration pages'),
@@ -3575,17 +3568,6 @@ function system_time_zones($blank = NULL) {
 }
 
 /**
- * Menu callback; Retrieve a JSON object containing a suggested time zone name.
- */
-function system_timezone($abbreviation = '', $offset = -1, $is_daylight_saving_time = NULL) {
-  // An abbreviation of "0" passed in the callback arguments should be
-  // interpreted as the empty string.
-  $abbreviation = $abbreviation ? $abbreviation : '';
-  $timezone = timezone_name_from_abbr($abbreviation, intval($offset), $is_daylight_saving_time);
-  return new JsonResponse($timezone);
-}
-
-/**
  * Returns HTML for the Powered by Drupal text.
  *
  * @ingroup themeable
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index 9859d6a..5023bdc 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -87,3 +87,10 @@ date_format_localize_reset:
     _form: '\Drupal\system\Form\DateFormatLocalizeResetForm'
   requirements:
     _permission: 'administer site configuration'
+
+system_timezone:
+  pattern: '/system/timezone'
+  defaults:
+    _controller: '\Drupal\system\TimezoneController::getTimezone'
+  requirements:
+    _access: 'TRUE'
