diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 34e5e7cdea7602c11e6c2fd25149706ab36ffda4..da41b23b525199aead22428c0d62898470300f58 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,11 @@ and this project adheres to `Semantic Versioning`_.
 Unreleased
 ----------
 
+Changed
+~~~~~~~
+
+* Announcements are shown in calendar.
+
 Fixed
 ~~~~~
 
diff --git a/aleksis/core/frontend/components/announcements/Announcements.vue b/aleksis/core/frontend/components/announcements/Announcements.vue
index 3529992700215d704fd869cd090cc7163c3deff7..ba7d534c850f54a02bdc90ddb86021a15eb587e5 100644
--- a/aleksis/core/frontend/components/announcements/Announcements.vue
+++ b/aleksis/core/frontend/components/announcements/Announcements.vue
@@ -20,11 +20,11 @@ import PositiveSmallIntegerField from "../generic/forms/PositiveSmallIntegerFiel
     item-attribute="title"
     :enable-edit="true"
   >
-    <template #validFrom="{ item }">
-      {{ $d($parseISODate(item.validFrom), "shortDateTime") }}
+    <template #datetimeStart="{ item }">
+      {{ $d($parseISODate(item.datetimeStart), "shortDateTime") }}
     </template>
     <!-- eslint-disable-next-line vue/valid-v-slot -->
-    <template #validFrom.field="{ attrs, on, item }">
+    <template #datetimeStart.field="{ attrs, on, item }">
       <div aria-required="true">
         <date-time-field
           dense
@@ -32,17 +32,17 @@ import PositiveSmallIntegerField from "../generic/forms/PositiveSmallIntegerFiel
           v-bind="attrs"
           v-on="on"
           required
-          :max="item.validUntil"
+          :max="item.datetimeEnd"
           :rules="$rules().required.build()"
         />
       </div>
     </template>
 
-    <template #validUntil="{ item }">
-      {{ $d($parseISODate(item.validUntil), "shortDateTime") }}
+    <template #datetimeEnd="{ item }">
+      {{ $d($parseISODate(item.datetimeEnd), "shortDateTime") }}
     </template>
     <!-- eslint-disable-next-line vue/valid-v-slot -->
-    <template #validUntil.field="{ attrs, on, item }">
+    <template #datetimeEnd.field="{ attrs, on, item }">
       <div aria-required="true">
         <date-time-field
           dense
@@ -50,7 +50,7 @@ import PositiveSmallIntegerField from "../generic/forms/PositiveSmallIntegerFiel
           v-bind="attrs"
           v-on="on"
           required
-          :min="$parseISODate(item.validFrom).plus({ minutes: 1 }).toISO()"
+          :min="$parseISODate(item.datetimeStart).plus({ minutes: 1 }).toISO()"
           :rules="$rules().required.build()"
         />
       </div>
@@ -150,12 +150,12 @@ export default {
       headers: [
         {
           text: this.$t("announcement.valid_from"),
-          value: "validFrom",
+          value: "datetimeStart",
           cols: 6,
         },
         {
           text: this.$t("announcement.valid_until"),
-          value: "validUntil",
+          value: "datetimeEnd",
           cols: 6,
         },
         {
@@ -190,10 +190,10 @@ export default {
       gqlPatchMutation: patchAnnouncements,
       gqlDeleteMutation: deleteAnnouncements,
       defaultItem: {
-        validFrom: DateTime.now()
+        datetimeStart: DateTime.now()
           .startOf("minute")
           .toISO({ suppressSeconds: true }),
-        validUntil: DateTime.now()
+        datetimeEnd: DateTime.now()
           .startOf("minute")
           .plus({ hours: 1 })
           .toISO({ suppressSeconds: true }),
diff --git a/aleksis/core/frontend/components/announcements/announcements.graphql b/aleksis/core/frontend/components/announcements/announcements.graphql
index 72ad657079c3680b6b68cd28c60d5846a444ecdd..c43bb4903caf35c2fcfd97ed466c7651e2bb4217 100644
--- a/aleksis/core/frontend/components/announcements/announcements.graphql
+++ b/aleksis/core/frontend/components/announcements/announcements.graphql
@@ -1,7 +1,7 @@
 fragment announcementFields on AnnouncementType {
   id
-  validFrom
-  validUntil
+  datetimeStart
+  datetimeEnd
   title
   description
   priority
diff --git a/aleksis/core/managers.py b/aleksis/core/managers.py
index 7fc89a5a7fa0495213ae072452569a17113095c2..5ae52e070785562eb29197e8df4b2e6e2f934c96 100644
--- a/aleksis/core/managers.py
+++ b/aleksis/core/managers.py
@@ -1,9 +1,11 @@
-from datetime import date
-from typing import TYPE_CHECKING, Union
+from datetime import date, datetime
+from typing import TYPE_CHECKING, Optional, Union
 
 from django.apps import apps
-from django.db.models import BooleanField, Case, QuerySet, Value, When
+from django.contrib.contenttypes.models import ContentType
+from django.db.models import BooleanField, Case, Model, QuerySet, Value, When
 from django.db.models.manager import Manager
+from django.utils import timezone
 
 from calendarweek import CalendarWeek
 from django_cte.cte import CTEQuerySet
@@ -225,3 +227,76 @@ class HolidayQuerySet(DateRangeQuerySetMixin, CalendarEventQuerySet):
 
 class HolidayManager(CalendarEventManager):
     queryset_class = HolidayQuerySet
+
+
+class AnnouncementQuerySet(CalendarEventQuerySet):
+    """Queryset for announcements providing time-based utility functions."""
+
+    def relevant_for(self, obj: Union[Model, QuerySet]) -> QuerySet:
+        """Get all relevant announcements.
+
+        Get a QuerySet with all announcements relevant for a certain Model (e.g. a Group)
+        or a set of models in a QuerySet.
+        """
+        if isinstance(obj, QuerySet):
+            ct = ContentType.objects.get_for_model(obj.model)
+            pks = list(obj.values_list("pk", flat=True))
+        else:
+            ct = ContentType.objects.get_for_model(obj)
+            pks = [obj.pk]
+
+        return self.filter(recipients__content_type=ct, recipients__recipient_id__in=pks)
+
+    def at_time(self, when: Optional[datetime] = None) -> QuerySet:
+        """Get all announcements at a certain time."""
+        when = when or timezone.now()
+
+        # Get announcements by time
+        announcements = self.filter(datetime_start__lte=when, datetime_end__gte=when)
+
+        return announcements
+
+    def on_date(self, when: Optional[date] = None) -> QuerySet:
+        """Get all announcements at a certain date."""
+        when = when or timezone.now().date()
+
+        # Get announcements by time
+        announcements = self.filter(datetime_start__date__lte=when, datetime_end__date__gte=when)
+
+        return announcements
+
+    def within_days(self, start: date, stop: date) -> QuerySet:
+        """Get all announcements valid for a set of days."""
+        # Get announcements
+        announcements = self.filter(datetime_start__date__lte=stop, datetime_end__date__gte=start)
+
+        return announcements
+
+    def for_person(self, person: "Person") -> list:  # noqa: F821
+        """Get all announcements for one person."""
+        # Filter by person
+        announcements_for_person = []
+        for announcement in self:
+            if person in announcement.recipient_persons:
+                announcements_for_person.append(announcement)
+
+        return announcements_for_person
+
+
+class AnnouncementManager(CalendarEventManager):
+    queryset_class = AnnouncementQuerySet
+
+    def relevant_for(self, obj: Union[Model, QuerySet]) -> QuerySet:
+        return self.get_queryset().relevant_for(obj)
+
+    def at_time(self, when: Optional[datetime] = None) -> QuerySet:
+        return self.get_queryset().at_time(when)
+
+    def on_date(self, when: Optional[date] = None) -> QuerySet:
+        return self.get_queryset().on_date(when)
+
+    def within_days(self, start: date, stop: date) -> QuerySet:
+        return self.get_queryset().within_days(start, stop)
+
+    def for_person(self, person: "Person") -> list:  # noqa: F821
+        return self.get_queryset().for_person(person)
diff --git a/aleksis/core/migrations/0081_migrate_announcements.py b/aleksis/core/migrations/0081_migrate_announcements.py
new file mode 100644
index 0000000000000000000000000000000000000000..b75ea4efed5a641ffca569d9b232b18d500cb6ef
--- /dev/null
+++ b/aleksis/core/migrations/0081_migrate_announcements.py
@@ -0,0 +1,44 @@
+# Generated by Django 5.1.7 on 2025-04-03 11:42
+
+import aleksis.core.mixins
+import django.db.models.deletion
+from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
+from django.db import migrations, models
+
+
+def migrate_announcements(apps, schema_editor):
+    CalendarEvent = apps.get_model("core", "CalendarEvent")
+    Announcement = apps.get_model("core", "Announcement")
+    announcement_ctype = ContentType.objects.get_for_model(Announcement)
+
+    db_alias = schema_editor.connection.alias
+
+    for announcement in Announcement.objects.all():
+        event = CalendarEvent.objects.create(
+            datetime_start=announcement.valid_from,
+            datetime_end=announcement.valid_until,
+            polymorphic_ctype_id = announcement_ctype.pk,
+            extended_data=announcement.extended_data,
+            managed_by_app_label=announcement.managed_by_app_label,
+        )
+
+        announcement.calendarevent_ptr_id = event.pk
+        announcement.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0080_remove_guardians'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='announcement',
+            name='calendarevent_ptr',
+            field=models.OneToOneField(auto_created=True, null=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, serialize=False, to='core.calendarevent'),
+        ),
+        migrations.RunPython(migrate_announcements),
+    ]
diff --git a/aleksis/core/migrations/0082_announcement_remove_fields.py b/aleksis/core/migrations/0082_announcement_remove_fields.py
new file mode 100644
index 0000000000000000000000000000000000000000..55cab8f7bfb2979f25192c9c59639ec44e928081
--- /dev/null
+++ b/aleksis/core/migrations/0082_announcement_remove_fields.py
@@ -0,0 +1,42 @@
+# Generated by Django 5.1.7 on 2025-04-03 11:42
+
+import aleksis.core.mixins
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0081_migrate_announcements'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='announcement',
+            name='id',
+        ),
+        migrations.AlterField(
+            model_name='announcement',
+            name='calendarevent_ptr',
+            field=models.OneToOneField(auto_created=True, null=False, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.calendarevent'),
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='extended_data',
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='managed_by_app_label',
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='valid_from',
+        ),
+        migrations.RemoveField(
+            model_name='announcement',
+            name='valid_until',
+        ),
+    ]
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index bb6e29a59e49b21f3477b38acb3749143f99c30b..8057f697ac6ec7aa77fdb19df68e846b5e3e4add 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -65,6 +65,7 @@ from aleksis.core.data_checks import (
 
 from .managers import (
     AlekSISBaseManagerWithoutMigrations,
+    AnnouncementManager,
     CalendarEventManager,
     CalendarEventMixinManager,
     GroupManager,
@@ -87,7 +88,7 @@ from .mixins import (
     SchoolTermRelatedExtensibleModel,
 )
 from .tasks import send_notification
-from .util.core_helpers import generate_random_code, get_site_preferences, now_tomorrow
+from .util.core_helpers import generate_random_code, get_site_preferences
 from .util.email import send_email
 from .util.model_helpers import ICONS
 
@@ -960,151 +961,6 @@ class Notification(ExtensibleModel, TimeStampedModel):
         ]
 
 
-class AnnouncementQuerySet(models.QuerySet):
-    """Queryset for announcements providing time-based utility functions."""
-
-    def relevant_for(self, obj: Union[models.Model, models.QuerySet]) -> models.QuerySet:
-        """Get all relevant announcements.
-
-        Get a QuerySet with all announcements relevant for a certain Model (e.g. a Group)
-        or a set of models in a QuerySet.
-        """
-        if isinstance(obj, models.QuerySet):
-            ct = ContentType.objects.get_for_model(obj.model)
-            pks = list(obj.values_list("pk", flat=True))
-        else:
-            ct = ContentType.objects.get_for_model(obj)
-            pks = [obj.pk]
-
-        return self.filter(recipients__content_type=ct, recipients__recipient_id__in=pks)
-
-    def at_time(self, when: Optional[datetime] = None) -> models.QuerySet:
-        """Get all announcements at a certain time."""
-        when = when or timezone.now()
-
-        # Get announcements by time
-        announcements = self.filter(valid_from__lte=when, valid_until__gte=when)
-
-        return announcements
-
-    def on_date(self, when: Optional[date] = None) -> models.QuerySet:
-        """Get all announcements at a certain date."""
-        when = when or timezone.now().date()
-
-        # Get announcements by time
-        announcements = self.filter(valid_from__date__lte=when, valid_until__date__gte=when)
-
-        return announcements
-
-    def within_days(self, start: date, stop: date) -> models.QuerySet:
-        """Get all announcements valid for a set of days."""
-        # Get announcements
-        announcements = self.filter(valid_from__date__lte=stop, valid_until__date__gte=start)
-
-        return announcements
-
-    def for_person(self, person: Person) -> list:
-        """Get all announcements for one person."""
-        # Filter by person
-        announcements_for_person = []
-        for announcement in self:
-            if person in announcement.recipient_persons:
-                announcements_for_person.append(announcement)
-
-        return announcements_for_person
-
-
-class Announcement(ExtensibleModel):
-    """Announcement model.
-
-    Persistent announcement to display to groups or persons in various places during a
-    specific time range.
-    """
-
-    objects = models.Manager.from_queryset(AnnouncementQuerySet)()
-
-    title = models.CharField(max_length=150, verbose_name=_("Title"))
-    description = models.TextField(max_length=500, verbose_name=_("Description"), blank=True)
-    link = models.URLField(blank=True, verbose_name=_("Link to detailed view"))
-    priority = models.PositiveSmallIntegerField(verbose_name=_("Priority"), blank=True, null=True)
-
-    valid_from = models.DateTimeField(
-        verbose_name=_("Date and time from when to show"), default=timezone.now
-    )
-    valid_until = models.DateTimeField(
-        verbose_name=_("Date and time until when to show"),
-        default=now_tomorrow,
-    )
-
-    @property
-    def recipient_persons(self) -> Sequence[Person]:
-        """Return a list of Persons this announcement is relevant for."""
-        persons = []
-        for recipient in self.recipients.all():
-            persons += recipient.persons
-        return persons
-
-    def get_recipients_for_model(self, obj: Union[models.Model]) -> Sequence[models.Model]:
-        """Get all recipients.
-
-        Get all recipients for this announcement
-        with a special content type (provided through model)
-        """
-        ct = ContentType.objects.get_for_model(obj)
-        return [r.recipient for r in self.recipients.filter(content_type=ct)]
-
-    def __str__(self):
-        return self.title
-
-    class Meta:
-        verbose_name = _("Announcement")
-        verbose_name_plural = _("Announcements")
-
-
-class AnnouncementRecipient(ExtensibleModel):
-    """Announcement recipient model.
-
-    Generalisation of a recipient for an announcement, used to wrap arbitrary
-    objects that can receive announcements.
-
-    Contract: Objects to serve as recipient have a property announcement_recipients
-    returning a flat list of Person objects.
-    """
-
-    announcement = models.ForeignKey(
-        Announcement, on_delete=models.CASCADE, related_name="recipients"
-    )
-
-    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
-    recipient_id = models.PositiveIntegerField()
-    recipient = GenericForeignKey("content_type", "recipient_id")
-
-    @property
-    def persons(self) -> Sequence[Person]:
-        """Return a list of Persons selected by this recipient object.
-
-        If the recipient is a Person, return that object. If not, it returns the list
-        from the announcement_recipients field on the target model.
-        """
-        if isinstance(self.recipient, Person):
-            return [self.recipient]
-        else:
-            return getattr(self.recipient, "announcement_recipients", [])
-
-    def __str__(self):
-        if hasattr(self.recipient, "short_name") and self.recipient.short_name:
-            return self.recipient.short_name
-        elif hasattr(self.recipient, "name") and self.recipient.name:
-            return self.recipient.name
-        elif hasattr(self.recipient, "full_name") and self.recipient.full_name:
-            return self.recipient.full_name
-        return str(self.recipient)
-
-    class Meta:
-        verbose_name = _("Announcement recipient")
-        verbose_name_plural = _("Announcement recipients")
-
-
 class DashboardWidget(RegistryObject, PolymorphicModel, PureDjangoModel):
     """Base class for dashboard widgets on the index page."""
 
@@ -1988,6 +1844,129 @@ class CalendarEvent(
         ordering = ["datetime_start", "date_start", "datetime_end", "date_end"]
 
 
+class Announcement(CalendarEvent):
+    """Announcement model.
+
+    Persistent announcement to display to groups or persons in various places during a
+    specific time range.
+    """
+
+    _class_name = "announcement"
+    dav_verbose_name = "Announcements"
+
+    objects = AnnouncementManager()
+
+    title = models.CharField(max_length=150, verbose_name=_("Title"))
+    description = models.TextField(max_length=500, verbose_name=_("Description"), blank=True)
+    link = models.URLField(blank=True, verbose_name=_("Link to detailed view"))
+    priority = models.PositiveSmallIntegerField(verbose_name=_("Priority"), blank=True, null=True)
+
+    @property
+    def valid_from(self):
+        return self.datetime_start
+
+    @property
+    def valid_until(self):
+        return self.datetime_end
+
+    @valid_from.setter
+    def valid_from(self, value):
+        self.datetime_start = value
+
+    @valid_until.setter
+    def valid_until(self, value):
+        self.datetime_end = value
+
+    @classmethod
+    def value_title(
+        cls, reference_object: "Announcement", request: HttpRequest | None = None
+    ) -> str:
+        """Return the title of the announcement."""
+        return reference_object.title
+
+    @classmethod
+    def value_description(
+        cls, reference_object: "Announcement", request: HttpRequest | None = None
+    ) -> str:
+        """Return the description of the announcement."""
+        return reference_object.description
+
+    @classmethod
+    def value_link(
+        cls, reference_object: "Announcement", request: HttpRequest | None = None
+    ) -> str:
+        """Return the link of the announcement."""
+        return reference_object.link
+
+    @property
+    def recipient_persons(self) -> Sequence[Person]:
+        """Return a list of Persons this announcement is relevant for."""
+        persons = []
+        for recipient in self.recipients.all():
+            persons += recipient.persons
+        return persons
+
+    def get_recipients_for_model(self, obj: Union[models.Model]) -> Sequence[models.Model]:
+        """Get all recipients.
+
+        Get all recipients for this announcement
+        with a special content type (provided through model)
+        """
+        ct = ContentType.objects.get_for_model(obj)
+        return [r.recipient for r in self.recipients.filter(content_type=ct)]
+
+    def __str__(self):
+        return self.title
+
+    class Meta:
+        verbose_name = _("Announcement")
+        verbose_name_plural = _("Announcements")
+
+
+class AnnouncementRecipient(ExtensibleModel):
+    """Announcement recipient model.
+
+    Generalisation of a recipient for an announcement, used to wrap arbitrary
+    objects that can receive announcements.
+
+    Contract: Objects to serve as recipient have a property announcement_recipients
+    returning a flat list of Person objects.
+    """
+
+    announcement = models.ForeignKey(
+        Announcement, on_delete=models.CASCADE, related_name="recipients"
+    )
+
+    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
+    recipient_id = models.PositiveIntegerField()
+    recipient = GenericForeignKey("content_type", "recipient_id")
+
+    @property
+    def persons(self) -> Sequence[Person]:
+        """Return a list of Persons selected by this recipient object.
+
+        If the recipient is a Person, return that object. If not, it returns the list
+        from the announcement_recipients field on the target model.
+        """
+        if isinstance(self.recipient, Person):
+            return [self.recipient]
+        else:
+            return getattr(self.recipient, "announcement_recipients", [])
+
+    def __str__(self):
+        if hasattr(self.recipient, "short_name") and self.recipient.short_name:
+            return self.recipient.short_name
+        elif hasattr(self.recipient, "name") and self.recipient.name:
+            return self.recipient.name
+        elif hasattr(self.recipient, "full_name") and self.recipient.full_name:
+            return self.recipient.full_name
+        return str(self.recipient)
+
+    class Meta:
+        verbose_name = _("Announcement recipient")
+        verbose_name_plural = _("Announcement recipients")
+
+
 class FreeBusy(CalendarEvent):
     _class_name = ""
 
diff --git a/aleksis/core/schema/announcement.py b/aleksis/core/schema/announcement.py
index 06820afcdc52d0475fff50fd7670fe64665338ca..af52ab7df3768a756040fd4c6dc17c65183dea04 100644
--- a/aleksis/core/schema/announcement.py
+++ b/aleksis/core/schema/announcement.py
@@ -23,8 +23,8 @@ class AnnouncementType(PermissionsTypeMixin, DjangoObjectType):
         model = Announcement
         fields = (
             "id",
-            "valid_from",
-            "valid_until",
+            "datetime_start",
+            "datetime_end",
             "title",
             "description",
             "priority",
@@ -45,8 +45,8 @@ class AnnouncementBatchCreateMutation(BaseBatchCreateMutation):
         model = Announcement
         permissions = ("core.create_announcement_rule",)
         only_fields = (
-            "valid_from",
-            "valid_until",
+            "datetime_start",
+            "datetime_end",
             "title",
             "description",
             "priority",
@@ -85,8 +85,8 @@ class AnnouncementBatchPatchMutation(BaseBatchPatchMutation):
         permissions = ("core.edit_announcement_rule",)
         only_fields = (
             "id",
-            "valid_from",
-            "valid_until",
+            "datetime_start",
+            "datetime_end",
             "title",
             "description",
             "priority",
diff --git a/aleksis/core/templates/core/partials/announcements.html b/aleksis/core/templates/core/partials/announcements.html
index e4aca139435db80aab86936d614f3a165e5183b6..c88055fb16366e961cdb2131d2a9e639eb1399d9 100644
--- a/aleksis/core/templates/core/partials/announcements.html
+++ b/aleksis/core/templates/core/partials/announcements.html
@@ -4,12 +4,12 @@
   <figure class="alert primary">
       {% if show_interval %}
         <em class="right hide-on-small-and-down">
-          {% if announcement.valid_from.date == announcement.valid_until.date %}
-            {% blocktrans with from=announcement.valid_from|naturalday %}
+          {% if announcement.datetime_start.date == announcement.datetime_end.date %}
+            {% blocktrans with from=announcement.datetime_start|naturalday %}
               Valid for {{ from }}
             {% endblocktrans %}
           {% else %}
-            {% blocktrans with from=announcement.valid_from|naturalday until=announcement.valid_until|naturalday %}
+            {% blocktrans with from=announcement.datetime_start|naturalday until=announcement.datetime_end|naturalday %}
               Valid from {{ from }} until {{ until }}
             {% endblocktrans %}
           {% endif %}
@@ -31,12 +31,12 @@
 
       {% if show_interval %}
         <em class="hide-on-med-and-up">
-          {% if announcement.valid_from.date == announcement.valid_until.date %}
-            {% blocktrans with from=announcement.valid_from|naturalday %}
+          {% if announcement.datetime_start.date == announcement.datetime_end.date %}
+            {% blocktrans with from=announcement.datetime_start|naturalday %}
               Valid for {{ from }}
             {% endblocktrans %}
           {% else %}
-            {% blocktrans with from=announcement.valid_from|naturalday until=announcement.valid_until|naturalday %}
+            {% blocktrans with from=announcement.datetime_start|naturalday until=announcement.datetime_end|naturalday %}
               Valid for {{ from }} – {{ until }}
             {% endblocktrans %}
           {% endif %}