diff --git a/app/Resources/icons/history.svg b/app/Resources/icons/history.svg
new file mode 100644
index 0000000000000000000000000000000000000000..684091df227fcb0b40123a5998967479270c17f0
--- /dev/null
+++ b/app/Resources/icons/history.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+    <path fill="none" d="M0 0H24V24H0z"/>
+    <path d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12h2c0 4.418 3.582 8 8 8s8-3.582 8-8-3.582-8-8-8C9.536 4 7.332 5.114 5.865 6.865L8 9H2V3l2.447 2.446C6.28 3.336 8.984 2 12 2zm1 5v4.585l3.243 3.243-1.415 1.415L11 12.413V7h2z"/>
+</svg>
diff --git a/app/Views/Components/IconButton.php b/app/Views/Components/IconButton.php
index f02c80788235de91411fe5e468691deebce86e38..636f755c91576ad3abc3e7a7ec26b854bd0b7f36 100644
--- a/app/Views/Components/IconButton.php
+++ b/app/Views/Components/IconButton.php
@@ -4,27 +4,28 @@ declare(strict_types=1);
 
 namespace App\Views\Components;
 
-use ViewComponents\Component;
-
-class IconButton extends Component
+class IconButton extends Button
 {
     public string $glyph = '';
 
-    public function render(): string
+    public function __construct(array $attributes)
     {
-        $attributes = [
+        $iconButtonAttributes = [
             'isSquared' => 'true',
-            'title' => $this->slot,
+            'title' => $attributes['slot'],
             'data-tooltip' => 'bottom',
         ];
 
-        $attributes = array_merge($attributes, $this->attributes);
+        $glyphSize = [
+            'small' => 'text-sm',
+            'base' => 'text-lg',
+            'large' => 'text-2xl',
+        ];
 
-        $attributes['slot'] = icon($this->glyph);
+        $allAttributes = array_merge($attributes, $iconButtonAttributes);
 
-        unset($attributes['glyph']);
+        parent::__construct($allAttributes);
 
-        $iconButton = new Button($attributes);
-        return $iconButton->render();
+        $this->slot = icon($this->glyph, $glyphSize[$this->size]);
     }
 }
diff --git a/modules/Admin/Config/Routes.php b/modules/Admin/Config/Routes.php
index 06aadf0e358a1c265b7b3af9897ae575c609f788..ad767a0d11e6bafe049d925998eec0241583fc0f 100644
--- a/modules/Admin/Config/Routes.php
+++ b/modules/Admin/Config/Routes.php
@@ -327,6 +327,23 @@ $routes->group(
                                     'permission:podcast-manage_publications',
                             ],
                         );
+                        $routes->get(
+                            'publish-date-edit',
+                            'EpisodeController::publishDateEdit/$1/$2',
+                            [
+                                'as' => 'episode-publish_date_edit',
+                                'filter' =>
+                                    'permission:podcast-manage_publications',
+                            ],
+                        );
+                        $routes->post(
+                            'publish-date-edit',
+                            'EpisodeController::attemptPublishDateEdit/$1/$2',
+                            [
+                                'filter' =>
+                                    'permission:podcast-manage_publications',
+                            ],
+                        );
                         $routes->get(
                             'unpublish',
                             'EpisodeController::unpublish/$1/$2',
diff --git a/modules/Admin/Controllers/EpisodeController.php b/modules/Admin/Controllers/EpisodeController.php
index 9e5e906f7044693fdef87043bbf9fe0e3da8ec3a..6c14d7f38597a5db4fd932b90549035c63cd7a36 100644
--- a/modules/Admin/Controllers/EpisodeController.php
+++ b/modules/Admin/Controllers/EpisodeController.php
@@ -683,29 +683,104 @@ class EpisodeController extends BaseController
         return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id]);
     }
 
-    public function unpublish(): string | RedirectResponse
+    public function publishDateEdit(): string|RedirectResponse
     {
-        if ($this->episode->publication_status === 'published') {
-            helper(['form']);
+        // only accessible if episode is already published
+        if ($this->episode->publication_status !== 'published') {
+            return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
+                'error',
+                lang('Episode.publish_date_edit_error')
+            );
+        }
 
-            $data = [
-                'podcast' => $this->podcast,
-                'episode' => $this->episode,
-            ];
+        helper('form');
 
-            replace_breadcrumb_params([
-                0 => $this->podcast->title,
-                1 => $this->episode->title,
-            ]);
-            return view('episode/unpublish', $data);
+        $data = [
+            'podcast' => $this->podcast,
+            'episode' => $this->episode,
+        ];
+
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->episode->title,
+        ]);
+
+        return view('episode/publish_date_edit', $data);
+    }
+
+    /**
+     * Allows to set an episode's publication date to a past date
+     *
+     * Prevents setting a future date as it does not make sense to set a future published date to an already published
+     * episode. This also prevents any side-effects from occurring.
+     */
+    public function attemptPublishDateEdit(): RedirectResponse
+    {
+        $rules = [
+            'new_publication_date' => 'valid_date[Y-m-d H:i]',
+        ];
+
+        if (! $this->validate($rules)) {
+            return redirect()
+                ->back()
+                ->withInput()
+                ->with('errors', $this->validator->getErrors());
+        }
+
+        $newPublicationDate = $this->request->getPost('new_publication_date');
+
+        $newPublicationDate = Time::createFromFormat(
+            'Y-m-d H:i',
+            $newPublicationDate,
+            $this->request->getPost('client_timezone'),
+        )->setTimezone(app_timezone());
+
+        if ($newPublicationDate->isAfter(Time::now())) {
+            return redirect()
+                ->back()
+                ->withInput()
+                ->with('error', lang('Episode.publish_date_edit_future_error'));
+        }
+
+        $this->episode->published_at = $newPublicationDate;
+
+        $episodeModel = new EpisodeModel();
+        if (! $episodeModel->update($this->episode->id, $this->episode)) {
+            return redirect()
+                ->back()
+                ->withInput()
+                ->with('errors', $episodeModel->errors());
         }
 
         return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
-            'error',
-            lang('Episode.unpublish_error')
+            'message',
+            lang('Episode.publish_date_edit_success')
         );
     }
 
+    public function unpublish(): string | RedirectResponse
+    {
+        if ($this->episode->publication_status !== 'published') {
+            return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
+                'error',
+                lang('Episode.unpublish_error')
+            );
+        }
+
+        helper(['form']);
+
+        $data = [
+            'podcast' => $this->podcast,
+            'episode' => $this->episode,
+        ];
+
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->episode->title,
+        ]);
+        return view('episode/unpublish', $data);
+    }
+
     public function attemptUnpublish(): RedirectResponse
     {
         $rules = [
diff --git a/modules/Admin/Language/en/Breadcrumb.php b/modules/Admin/Language/en/Breadcrumb.php
index 46863af3bba195ac1a71c61b4eac718652fe52e8..f3269bfa4e45e583492211d3e7177cd933dcaaeb 100644
--- a/modules/Admin/Language/en/Breadcrumb.php
+++ b/modules/Admin/Language/en/Breadcrumb.php
@@ -25,6 +25,7 @@ return [
     'persons' => 'persons',
     'publish' => 'publish',
     'publish-edit' => 'edit publication',
+    'publish-date-edit' => 'edit publication date',
     'unpublish' => 'unpublish',
     'delete' => 'delete',
     'fediverse' => 'fediverse',
diff --git a/modules/Admin/Language/en/Episode.php b/modules/Admin/Language/en/Episode.php
index 92631ddf1c95dba582232b069567e7e91bb110e9..91313a7c5aa4d299bfd17c32825c0945a915c2bb 100644
--- a/modules/Admin/Language/en/Episode.php
+++ b/modules/Admin/Language/en/Episode.php
@@ -24,10 +24,14 @@ return [
     'edit' => 'Edit',
     'publish' => 'Publish',
     'publish_edit' => 'Edit publication',
+    'publish_date_edit' => 'Edit publication date',
     'unpublish' => 'Unpublish',
     'publish_error' => 'Episode is already published.',
     'publish_edit_error' => 'Episode is already published.',
     'publish_cancel_error' => 'Episode is already published.',
+    'publish_date_edit_error' => 'Episode has not been published yet, you cannot edit its publication date.',
+    'publish_date_edit_future_error' => 'Episode\'s publication date can only be set to a past date! If you would like to reschedule it, unpublish it first.',
+    'publish_date_edit_success' => 'Episode\'s publication date has been updated successfully!',
     'unpublish_error' => 'Episode is not published.',
     'delete' => 'Delete',
     'go_to_page' => 'Go to page',
@@ -178,6 +182,11 @@ return [
         'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.',
         'message_warning_submit' => 'Publish anyways',
     ],
+    'publish_date_edit_form' => [
+        'new_publication_date' => 'New publication date',
+        'new_publication_date_hint' => 'Must be set to a past date.',
+        'submit' => 'Edit publication date',
+    ],
     'unpublish_form' => [
         'disclaimer' =>
             "Unpublishing the episode will delete all the comments and posts associated with it and remove it from the podcast's RSS feed.",
diff --git a/themes/cp_admin/_layout.php b/themes/cp_admin/_layout.php
index 78e41ca00fe2a59d0902a427cbc811b8f2a5701b..d23a48a463dcb6daa7f9bfbcfad0ed2d04f00e00 100644
--- a/themes/cp_admin/_layout.php
+++ b/themes/cp_admin/_layout.php
@@ -1,3 +1,9 @@
+<?php declare(strict_types=1);
+
+$isPodcastArea = isset($podcast) && ! isset($episode);
+$isEpisodeArea = isset($podcast) && isset($episode);
+?>
+
 <!DOCTYPE html>
 <html lang="<?= service('request')
     ->getLocale() ?>">
@@ -32,9 +38,9 @@
                 <?= render_breadcrumb('text-xs items-center flex') ?>
                 <div class="flex justify-between py-1">
                     <div class="flex flex-wrap items-center">
-                    <?php if ((isset($episode) && $episode->is_premium) || (isset($podcast) && $podcast->is_premium)): ?>
+                    <?php if (($isEpisodeArea && $episode->is_premium) || ($isPodcastArea && $podcast->is_premium)): ?>
                         <div class="inline-flex items-center">
-                            <IconButton uri="<?= route_to('subscription-list', $podcast->id) ?>" glyph="exchange-dollar" variant="secondary" class="p-0 mr-2 text-4xl border-0"><?= isset($episode) ? lang('PremiumPodcasts.episode_is_premium') : lang('PremiumPodcasts.podcast_is_premium') ?></IconButton>
+                            <IconButton uri="<?= route_to('subscription-list', $podcast->id) ?>" glyph="exchange-dollar" variant="secondary" size="large" class="p-0 mr-2 border-0"><?= ($isEpisodeArea && $episode->is_premium) ? lang('PremiumPodcasts.episode_is_premium') : lang('PremiumPodcasts.podcast_is_premium') ?></IconButton>
                             <Heading tagName="h1" size="large" class="truncate"><?= $this->renderSection('pageTitle') ?></Heading>
                         </div>
                         <?php else: ?>
@@ -42,11 +48,11 @@
                         <?php endif; ?>
                         <?= $this->renderSection('headerLeft') ?>
                     </div>
-                    <div class="flex flex-shrink-0 gap-x-2"><?= $this->renderSection('headerRight') ?></div>
+                    <div class="flex items-center flex-shrink-0 gap-x-2"><?= $this->renderSection('headerRight') ?></div>
                 </div>
             </div>
         </header>
-        <?php if (isset($podcast) && $podcast->publication_status !== 'published'): ?>
+        <?php if ($isPodcastArea && $podcast->publication_status !== 'published'): ?>
                 <?= publication_status_banner($podcast->published_at, $podcast->id, $podcast->publication_status) ?>
         <?php endif ?>
         <div class="px-2 py-8 mx-auto md:px-12">
diff --git a/themes/cp_admin/_partials/_nav_aside.php b/themes/cp_admin/_partials/_nav_aside.php
index 79ff2a87f611c98aacbf9c50af1e60e8efd8c82f..eddfc4b0068284814597606981446002e1dd787e 100644
--- a/themes/cp_admin/_partials/_nav_aside.php
+++ b/themes/cp_admin/_partials/_nav_aside.php
@@ -1,8 +1,14 @@
+<?php declare(strict_types=1);
+
+$isPodcastArea = isset($podcast) && ! isset($episode);
+$isEpisodeArea = isset($podcast) && isset($episode);
+?>
+
 <div data-sidebar-toggler="backdrop" role="button" tabIndex="0" aria-label="<?= lang('Common.close') ?>" class="fixed z-50 hidden w-full h-full bg-gray-800/75 md:hidden"></div>
 <aside data-sidebar-toggler="sidebar" data-toggle-class="-translate-x-full" data-hide-class="-translate-x-full" class="h-full max-h-[calc(100vh-40px)] sticky z-50 flex flex-col row-start-2 col-start-1 text-white transition duration-200 ease-in-out transform -translate-x-full border-r top-10 border-navigation bg-navigation md:translate-x-0">
-    <?php if (isset($podcast) && isset($episode)): ?>
+    <?php if ($isEpisodeArea): ?>
         <?= $this->include('episode/_sidebar') ?>
-    <?php elseif (isset($podcast)): ?>
+    <?php elseif ($isPodcastArea): ?>
         <?= $this->include('podcast/_sidebar') ?>
     <?php else: ?>
         <?= $this->include('_sidebar') ?>
diff --git a/themes/cp_admin/episode/publish_date_edit.php b/themes/cp_admin/episode/publish_date_edit.php
new file mode 100644
index 0000000000000000000000000000000000000000..7346e659cc55ede83b60daeaa5d91880f73b4690
--- /dev/null
+++ b/themes/cp_admin/episode/publish_date_edit.php
@@ -0,0 +1,38 @@
+<?= $this->extend('_layout') ?>
+
+<?= $this->section('title') ?>
+<?= lang('Episode.publish_date_edit') ?>
+<?= $this->endSection() ?>
+
+<?= $this->section('pageTitle') ?>
+<?= lang('Episode.publish_date_edit') ?>
+<?= $this->endSection() ?>
+
+<?= $this->section('content') ?>
+
+<?= anchor(
+    route_to('episode-view', $podcast->id, $episode->id),
+    icon('arrow-left', 'mr-2 text-lg') . lang('Episode.publish_form.back_to_episode_dashboard'),
+    [
+        'class' => 'inline-flex items-center font-semibold mr-4 text-sm',
+    ],
+) ?>
+
+<form action="<?= route_to('episode-publish_date_edit', $podcast->id, $episode->id) ?>" method="POST" class="flex flex-col items-start w-full max-w-lg mx-auto mt-4" data-submit="validate-message">
+<?= csrf_field() ?>
+<input type="hidden" name="client_timezone" value="UTC" />
+
+<Forms.Field
+    as="DatetimePicker"
+    name="new_publication_date"
+    label="<?= lang('Episode.publish_date_edit_form.new_publication_date') ?>"
+    hint="<?= lang('Episode.publish_date_edit_form.new_publication_date_hint') ?>"
+    value="<?= $episode->published_at ?>"
+    required="true"
+/>
+
+<Button variant="primary" type="submit" class="mt-4"><?= lang('Episode.publish_date_edit_form.submit') ?></Button>
+
+</form>
+
+<?= $this->endSection() ?>
diff --git a/themes/cp_admin/episode/view.php b/themes/cp_admin/episode/view.php
index 0d42adf5c489a94269482f4722305f8ced4681e5..6357011e04e93b410976b6670b684d62a906ea28 100644
--- a/themes/cp_admin/episode/view.php
+++ b/themes/cp_admin/episode/view.php
@@ -17,6 +17,14 @@
 <?= $this->endSection() ?>
 
 <?= $this->section('headerRight') ?>
+<?php if ($episode->publication_status === 'published'): ?>
+<IconButton
+    uri="<?= route_to('episode-publish_date_edit', $podcast->id, $episode->id) ?>"
+    glyph="history"
+    variant="secondary"
+    glyphClass="text-xl"
+><?= lang('Episode.publish_date_edit') ?></IconButton>
+<?php endif; ?>
 <?= publication_button(
     $podcast->id,
     $episode->id,