diff --git a/core/lib/Drupal/Component/Datetime/Time.php b/core/lib/Drupal/Component/Datetime/Time.php
index 566debba0494cacae2002c92a674564c97396748..ec660094fc985c88d5c17948a80783ed38b54fe8 100644
--- a/core/lib/Drupal/Component/Datetime/Time.php
+++ b/core/lib/Drupal/Component/Datetime/Time.php
@@ -6,23 +6,32 @@
 
 /**
  * Provides a class for obtaining system time.
+ *
+ * While the normal use case of this class expects that a Request object is
+ * available from the RequestStack, it is still possible to use it without, for
+ * example for early bootstrap containers or for unit tests. In those cases,
+ * the class will access global variables or set a proxy request time in order
+ * to return the request time.
  */
 class Time implements TimeInterface {
 
   /**
    * The request stack.
-   *
-   * @var \Symfony\Component\HttpFoundation\RequestStack
    */
-  protected $requestStack;
+  protected ?RequestStack $requestStack;
+
+  /**
+   * A proxied request time if the request time is not available.
+   */
+  protected float $proxyRequestTime;
 
   /**
    * Constructs a Time object.
    *
-   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
-   *   The request stack.
+   * @param \Symfony\Component\HttpFoundation\RequestStack|null $request_stack
+   *   (Optional) The request stack.
    */
-  public function __construct(RequestStack $request_stack) {
+  public function __construct(RequestStack $request_stack = NULL) {
     $this->requestStack = $request_stack;
   }
 
@@ -30,26 +39,26 @@ public function __construct(RequestStack $request_stack) {
    * {@inheritdoc}
    */
   public function getRequestTime() {
-    $request = $this->requestStack->getCurrentRequest();
+    $request = $this->requestStack ? $this->requestStack->getCurrentRequest() : NULL;
     if ($request) {
       return $request->server->get('REQUEST_TIME');
     }
     // If this is called prior to the request being pushed to the stack fallback
     // to built-in globals (if available) or the system time.
-    return $_SERVER['REQUEST_TIME'] ?? $this->getCurrentTime();
+    return $_SERVER['REQUEST_TIME'] ?? $this->getProxyRequestTime();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getRequestMicroTime() {
-    $request = $this->requestStack->getCurrentRequest();
+    $request = $this->requestStack ? $this->requestStack->getCurrentRequest() : NULL;
     if ($request) {
       return $request->server->get('REQUEST_TIME_FLOAT');
     }
     // If this is called prior to the request being pushed to the stack fallback
     // to built-in globals (if available) or the system time.
-    return $_SERVER['REQUEST_TIME_FLOAT'] ?? $this->getCurrentMicroTime();
+    return $_SERVER['REQUEST_TIME_FLOAT'] ?? $this->getProxyRequestMicroTime();
   }
 
   /**
@@ -66,4 +75,30 @@ public function getCurrentMicroTime() {
     return microtime(TRUE);
   }
 
+  /**
+   * Returns a mimic of the timestamp of the current request.
+   *
+   * @return int
+   *   A value returned by time().
+   */
+  protected function getProxyRequestTime(): int {
+    if (!isset($this->proxyRequestTime)) {
+      $this->proxyRequestTime = $this->getCurrentMicroTime();
+    }
+    return (int) $this->proxyRequestTime;
+  }
+
+  /**
+   * Returns a mimic of the timestamp of the current request.
+   *
+   * @return float
+   *   A value returned by microtime().
+   */
+  protected function getProxyRequestMicroTime(): float {
+    if (!isset($this->proxyRequestTime)) {
+      $this->proxyRequestTime = $this->getCurrentMicroTime();
+    }
+    return $this->proxyRequestTime;
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
index 98dc0e6b53d836733501aa4409a048eecb5754cd..cf6016c7e5c67d911f0e7937d70522fcb069737e 100644
--- a/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
+++ b/core/tests/Drupal/Tests/Component/Datetime/TimeTest.php
@@ -83,7 +83,9 @@ public function testGetRequestMicroTime() {
    * @covers ::getRequestTime
    */
   public function testGetRequestTimeNoRequest() {
-    $expected = 12345678;
+    // With no request, and no global variable, we expect to get the int part
+    // of the microtime.
+    $expected = 1234567;
     unset($_SERVER['REQUEST_TIME']);
     $this->assertEquals($expected, $this->time->getRequestTime());
     $_SERVER['REQUEST_TIME'] = 23456789;
diff --git a/core/tests/Drupal/Tests/Component/Datetime/TimeWithNoRequestTest.php b/core/tests/Drupal/Tests/Component/Datetime/TimeWithNoRequestTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..c66e1bb440076a4d7ea6414cc41bdad362f9a459
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Datetime/TimeWithNoRequestTest.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace Drupal\Tests\Component\Datetime;
+
+use Drupal\Component\Datetime\Time;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Tests that getRequest(Micro)Time works when no underlying request exists.
+ *
+ * @coversDefaultClass \Drupal\Component\Datetime\Time
+ * @group Datetime
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ */
+class TimeWithNoRequestTest extends TestCase {
+
+  /**
+   * The time class for testing.
+   */
+  protected Time $time;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    // We need to explicitly unset the $_SERVER variables, so that Time is
+    // forced to look for current time.
+    unset($_SERVER['REQUEST_TIME']);
+    unset($_SERVER['REQUEST_TIME_FLOAT']);
+
+    $this->time = new Time();
+  }
+
+  /**
+   * Tests the getRequestTime method.
+   *
+   * @covers ::getRequestTime
+   */
+  public function testGetRequestTimeImmutable(): void {
+    $requestTime = $this->time->getRequestTime();
+    sleep(2);
+    $this->assertSame($requestTime, $this->time->getRequestTime());
+  }
+
+  /**
+   * Tests the getRequestMicroTime method.
+   *
+   * @covers ::getRequestMicroTime
+   */
+  public function testGetRequestMicroTimeImmutable() {
+    $requestTime = $this->time->getRequestMicroTime();
+    usleep(20000);
+    $this->assertSame($requestTime, $this->time->getRequestMicroTime());
+  }
+
+}