diff --git a/src/components/announcement/announcement.js b/src/components/announcement/announcement.js
index b1f5ee77..309eecea 100644
--- a/src/components/announcement/announcement.js
+++ b/src/components/announcement/announcement.js
@@ -1,6 +1,21 @@
 import { mapState } from 'vuex'
+import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
+import localeService from '../../services/locale/locale.service.js'
 
 const Announcement = {
+  components: {
+    AnnouncementEditor
+  },
+  data () {
+    return {
+      editing: false,
+      newAnnouncement: {
+        content: '',
+        startsAt: undefined,
+        endsAt: undefined
+      }
+    }
+  },
   props: {
     announcement: Object
   },
@@ -13,6 +28,22 @@ const Announcement = {
     },
     isRead () {
       return this.announcement.read
+    },
+    startsAt () {
+      const time = this.announcement['starts_at']
+      if (!time) {
+        return
+      }
+
+      return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
+    },
+    endsAt () {
+      const time = this.announcement['ends_at']
+      if (!time) {
+        return
+      }
+
+      return this.formatTimeOrDate(time, localeService.internalToBrowserLocale(this.$i18n.locale))
     }
   },
   methods: {
@@ -23,6 +54,10 @@ const Announcement = {
     },
     deleteAnnouncement () {
       return this.$store.dispatch('deleteAnnouncement', this.announcement.id)
+    },
+    formatTimeOrDate (time, locale) {
+      const d = new Date(time)
+      return this.announcement['all_day'] ? d.toLocaleDateString(locale) : d.toLocaleString(locale)
     }
   }
 }
diff --git a/src/components/announcement/announcement.vue b/src/components/announcement/announcement.vue
index d6f35b9f..5ddeebf5 100644
--- a/src/components/announcement/announcement.vue
+++ b/src/components/announcement/announcement.vue
@@ -5,27 +5,42 @@
     </div>
     <div class="body">
       <rich-content
+        v-if="!editing"
         :html="content"
         :emoji="announcement.emojis"
         :handle-links="true"
       />
+      <announcement-editor
+        v-else
+        :announcement="newAnnouncement"
+      />
     </div>
     <div class="footer">
-      <button
-        v-if="currentUser"
-        class="btn button-default"
-        :class="{ toggled: isRead }"
-        @click="markAsRead"
-      >
-        {{ $t('announcements.mark_as_read_action') }}
-      </button>
-      <button
-        v-if="currentUser && currentUser.role === 'admin'"
-        class="btn button-default"
-        @click="deleteAnnouncement"
-      >
-        {{ $t('announcements.delete_action') }}
-      </button>
+      <div class="times">
+        <span v-if="startsAt">
+          {{ $t('announcements.start_time_display', { time: startsAt }) }}
+        </span>
+        <span v-if="endsAt">
+          {{ $t('announcements.end_time_display', { time: endsAt }) }}
+        </span>
+      </div>
+      <div class="actions">
+        <button
+          v-if="currentUser"
+          class="btn button-default"
+          :class="{ toggled: isRead }"
+          @click="markAsRead"
+        >
+          {{ $t('announcements.mark_as_read_action') }}
+        </button>
+        <button
+          v-if="currentUser && currentUser.role === 'admin'"
+          class="btn button-default"
+          @click="deleteAnnouncement"
+        >
+          {{ $t('announcements.delete_action') }}
+        </button>
+      </div>
     </div>
   </div>
 </template>
@@ -47,6 +62,15 @@
   }
 
   .footer {
+    display: flex;
+    flex-direction: column;
+    .times {
+      display: flex;
+      flex-direction: column;
+    }
+  }
+
+  .footer .actions {
     display: flex;
     flex-direction: row;
     justify-content: space-around;
diff --git a/src/components/announcement_editor/announcement_editor.js b/src/components/announcement_editor/announcement_editor.js
new file mode 100644
index 00000000..79a03afe
--- /dev/null
+++ b/src/components/announcement_editor/announcement_editor.js
@@ -0,0 +1,13 @@
+import Checkbox from '../checkbox/checkbox.vue'
+
+const AnnouncementEditor = {
+  components: {
+    Checkbox
+  },
+  props: {
+    announcement: Object,
+    disabled: Boolean
+  }
+}
+
+export default AnnouncementEditor
diff --git a/src/components/announcement_editor/announcement_editor.vue b/src/components/announcement_editor/announcement_editor.vue
new file mode 100644
index 00000000..e2418b8d
--- /dev/null
+++ b/src/components/announcement_editor/announcement_editor.vue
@@ -0,0 +1,52 @@
+<template>
+  <div class="announcement-editor">
+    <textarea
+      ref="textarea"
+      v-model="announcement.content"
+      class="post-textarea"
+      rows="1"
+      cols="1"
+      :placeholder="$t('announcements.post_placeholder')"
+      :disabled="disabled"
+    />
+    <span class="announcement-metadata">
+      <label for="announcement-start-time">{{ $t('announcements.start_time_prompt') }}</label>
+      <input
+        id="announcement-start-time"
+        v-model="announcement.startsAt"
+        :type="announcement.allDay ? 'date' : 'datetime-local'"
+        :disabled="disabled"
+      >
+    </span>
+    <span class="announcement-metadata">
+      <label for="announcement-end-time">{{ $t('announcements.end_time_prompt') }}</label>
+      <input
+        id="announcement-end-time"
+        v-model="announcement.endsAt"
+        :type="announcement.allDay ? 'date' : 'datetime-local'"
+        :disabled="disabled"
+      >
+    </span>
+    <span class="announcement-metadata">
+      <Checkbox
+        id="announcement-all-day"
+        v-model="announcement.allDay"
+        :disabled="disabled"
+      />
+      <label for="announcement-all-day">{{ $t('announcements.all_day_prompt') }}</label>
+    </span>
+  </div>
+</template>
+
+<script src="./announcement_editor.js"></script>
+
+<style lang="scss">
+    .announcement-editor {
+      display: flex;
+      align-items: stretch;
+      flex-direction: column;
+      .announcement-metadata {
+        margin-top: 0.5em;
+      }
+    }
+</style>
diff --git a/src/components/announcements_page/announcements_page.js b/src/components/announcements_page/announcements_page.js
index 30759533..0bb4892e 100644
--- a/src/components/announcements_page/announcements_page.js
+++ b/src/components/announcements_page/announcements_page.js
@@ -1,11 +1,11 @@
 import { mapState } from 'vuex'
 import Announcement from '../announcement/announcement.vue'
-import Checkbox from '../checkbox/checkbox.vue'
+import AnnouncementEditor from '../announcement_editor/announcement_editor.vue'
 
 const AnnouncementsPage = {
   components: {
     Announcement,
-    Checkbox
+    AnnouncementEditor
   },
   data () {
     return {
diff --git a/src/components/announcements_page/announcements_page.vue b/src/components/announcements_page/announcements_page.vue
index e81edee1..54307c4d 100644
--- a/src/components/announcements_page/announcements_page.vue
+++ b/src/components/announcements_page/announcements_page.vue
@@ -14,38 +14,10 @@
             <h4>{{ $t('announcements.post_form_header') }}</h4>
           </div>
           <div class="body">
-            <textarea
-              ref="textarea"
-              v-model="newAnnouncement.content"
-              class="post-textarea"
-              rows="1"
-              cols="1"
-              :placeholder="$t('announcements.post_placeholder')"
+            <announcement-editor
+              :announcement="newAnnouncement"
               :disabled="posting"
             />
-            <span class="announcement-metadata">
-              <label for="announcement-start-time">{{ $t('announcements.start_time_prompt') }}</label>
-              <input
-                id="announcement-start-time"
-                v-model="newAnnouncement.startsAt"
-                :type="newAnnouncement.allDay ? 'date' : 'datetime-local'"
-              >
-            </span>
-            <span class="announcement-metadata">
-              <label for="announcement-end-time">{{ $t('announcements.end_time_prompt') }}</label>
-              <input
-                id="announcement-end-time"
-                v-model="newAnnouncement.endsAt"
-                :type="newAnnouncement.allDay ? 'date' : 'datetime-local'"
-              >
-            </span>
-            <span class="announcement-metadata">
-              <Checkbox
-                id="announcement-all-day"
-                v-model="newAnnouncement.allDay"
-              />
-              <label for="announcement-all-day">{{ $t('announcements.all_day_prompt') }}</label>
-            </span>
           </div>
           <div class="footer">
             <button
@@ -99,15 +71,6 @@
       margin-bottom: var(--status-margin, $status-margin);
     }
 
-    .body {
-      display: flex;
-      align-items: stretch;
-      flex-direction: column;
-      .announcement-metadata {
-        margin-top: 0.5em;
-      }
-    }
-
     .post-textarea {
       resize: vertical;
       height: 10em;
diff --git a/src/modules/announcements.js b/src/modules/announcements.js
index ddc51c33..a42acf93 100644
--- a/src/modules/announcements.js
+++ b/src/modules/announcements.js
@@ -28,7 +28,12 @@ const announcements = {
   mutations,
   actions: {
     fetchAnnouncements (store) {
-      return store.rootState.api.backendInteractor.fetchAnnouncements()
+      const currentUser = store.rootState.users.currentUser
+      const isAdmin = currentUser && currentUser.role === 'admin'
+
+      return (isAdmin
+        ? store.rootState.api.backendInteractor.adminFetchAnnouncements()
+        : store.rootState.api.backendInteractor.fetchAnnouncements())
         .then(announcements => {
           store.commit('setAnnouncements', announcements)
         })
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index bcc4e7b7..b24c688c 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -89,6 +89,7 @@ const PLEROMA_CHAT_URL = id => `/api/v1/pleroma/chats/by-account-id/${id}`
 const PLEROMA_CHAT_MESSAGES_URL = id => `/api/v1/pleroma/chats/${id}/messages`
 const PLEROMA_CHAT_READ_URL = id => `/api/v1/pleroma/chats/${id}/read`
 const PLEROMA_DELETE_CHAT_MESSAGE_URL = (chatId, messageId) => `/api/v1/pleroma/chats/${chatId}/messages/${messageId}`
+const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements'
 const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements'
 const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
 
@@ -1085,6 +1086,10 @@ const dismissNotification = ({ credentials, id }) => {
   })
 }
 
+const adminFetchAnnouncements = ({ credentials }) => {
+  return promisedRequest({ url: PLEROMA_ANNOUNCEMENTS_URL, credentials })
+}
+
 const fetchAnnouncements = ({ credentials }) => {
   return promisedRequest({ url: MASTODON_ANNOUNCEMENTS_URL, credentials })
 }
@@ -1402,7 +1407,8 @@ const apiService = {
   fetchAnnouncements,
   dismissAnnouncement,
   postAnnouncement,
-  deleteAnnouncement
+  deleteAnnouncement,
+  adminFetchAnnouncements
 }
 
 export default apiService