diff --git a/VERSIONS_HOTLINE/147824 b/VERSIONS_HOTLINE/147824
new file mode 100644
index 0000000000000000000000000000000000000000..566275f6e40aab1ea148d5613de12f1ced362de2
--- /dev/null
+++ b/VERSIONS_HOTLINE/147824
@@ -0,0 +1 @@
+ - correctif #147824 : Agenda : Amélioration de l'affichage des événements sans horaire de fin
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Article/RenderEventTiming.php b/library/ZendAfi/View/Helper/Article/RenderEventTiming.php
index 3912fc929e1e8a7b608e8741de6f69412b96c618..597335556a3f013d2e862dd8546c9b9318b48b85 100644
--- a/library/ZendAfi/View/Helper/Article/RenderEventTiming.php
+++ b/library/ZendAfi/View/Helper/Article/RenderEventTiming.php
@@ -41,65 +41,86 @@ class ZendAfi_View_Helper_Article_RenderEventTiming extends ZendAfi_View_Helper_
   }
 
 
+  public function _formatEventString(int $date_start,
+                                     int $date_end,
+                                     string $time_start,
+                                     string $time_end,
+                                     bool $all_day,
+                                     array $picked_days) : string {
+    if ($date_start == $date_end)
+      return $this->_formatOneDay($date_start, $time_start, $time_end, $all_day);
 
-  public function _formatEventString($date_start,
-                                     $date_end,
-                                     $time_start,
-                                     $time_end,
-                                     $all_day,
-                                     $picked_days) {
-    if ($date_start == $date_end) {
+    $year_start = $this->_yearFrom($date_start);
+    $year_end = $this->_yearFrom($date_end);
+
+    $month_start = $this->_monthFrom($date_start);
+    $month_end = $this->_monthFrom($date_end);
+
+    if ($month_start == $month_end && $year_start == $year_end)
+      $month_start = '';
+
+    if ($year_start == $year_end)
+      $year_start = '';
+
+    if (empty($picked_days) || 7 == count($picked_days))
+      return $this->_('Du %s au %s',
+                      $this->_dayNameAndNumberFrom($date_start, $month_start, $year_start),
+                      $this->_dayNameAndNumberFrom($date_end, $month_end, $year_end));
+
+    return $this->_('Les %s du %s au %s',
+                    $this->_getTextualDays($picked_days),
+                    $this->_dayNumberFrom($date_start, $month_start, $year_start),
+                    $this->_dayNumberFrom($date_end, $month_end, $year_end));
+  }
+
+
+  protected function _formatOneDay(int $date_start, string $time_start, string $time_end, bool $all_day) : string {
       $event_string = strftime('%A %d %B %Y', $date_start);
 
-      if ($all_day)
+      if ($all_day || '00:00' === $time_start)
         return $event_string;
 
-      return $event_string . (($time_start == $time_end)  ? $this->_(' à %s', $time_start)
-                                                          : $this->_(' de %s à %s', $time_start, $time_end));
-    }
+      return $event_string . ($time_start == $time_end
+                              ? $this->_(' à %s', $time_start)
+                              : $this->_(' de %s à %s', $time_start, $time_end));
+  }
 
-    $year_start = strftime('%Y', $date_start);
-    $year_end = strftime('%Y', $date_end);
 
-    $month_start = strftime('%B', $date_start);
-    $month_end = strftime('%B', $date_end);
+  protected function _yearFrom(int $timestamp) : string {
+    return strftime('%Y', $timestamp);
+  }
 
 
-    if ($month_start == $month_end && $year_start == $year_end)
-      $month_start = '';
+  protected function _monthFrom(int $timestamp) : string {
+    return strftime('%B', $timestamp);
+  }
 
-    if ($year_start == $year_end)
-      $year_start = '';
 
-    if(empty($picked_days) || 7 == count($picked_days))
-      return $this->_('Du %s au %s',
-                      trim(strftime('%A %d', $date_start) . ' ' . $month_start . ' ' . $year_start),
-                      trim(strftime('%A %d', $date_end) . ' ' . $month_end . ' ' . $year_end));
+  protected function _dayNameAndNumberFrom(int $timestamp, string $month, string $year) : string {
+    return trim(strftime('%A %d', $timestamp) . ' ' . $month . ' ' . $year);
+  }
 
-    $open_days = $this->getTextualDays($picked_days);
 
-    return $this->_('Les ' . $open_days . ' du %s au %s',
-                    trim(strftime('%e', $date_start) . ' ' . $month_start . ' ' . $year_start),
-                    trim(strftime('%e', $date_end) . ' ' . $month_end . ' ' . $year_end));
+  protected function _dayNumberFrom(int $timestamp, string $month, string $year) : string {
+    return trim(strftime('%e', $timestamp) . ' ' . $month . ' ' . $year);
   }
 
 
-  protected function getTextualDays($days) {
-    if(1 == count($days))
-      return  $this->_('%ss', $this->numericDayToTextual($days[0]));
+  protected function _getTextualDays(array $days) : string {
+    if (1 == count($days))
+      return $this->_('%ss', $this->_numericDayToTextual($days[0]));
 
     $last = array_pop($days);
-    $last = $this->_('%ss', $this->numericDayToTextual($last));
+    $last = $this->_('%ss', $this->_numericDayToTextual($last));
 
-    $textual_days = '';
-    foreach($days as $day)
-      $textual_days.= $this->_('%ss, ', $this->numericDayToTextual($day));
+    $textual_days = array_map(fn($day) => $this->_('%ss', $this->_numericDayToTextual($day)),
+                              $days);
 
-    return substr($textual_days, 0, -2) . $this->_(' et ') . $last;
+    return implode(', ', $textual_days) . $this->_(' et ') . $last;
   }
 
 
-  protected function numericDayToTextual($nb) {
+  protected function _numericDayToTextual($nb) : string {
     return strftime('%A', strtotime('Sunday +' . $nb . ' days'));
   }
 }
diff --git a/library/templates/Intonation/Library/View/Wrapper/Article.php b/library/templates/Intonation/Library/View/Wrapper/Article.php
index 947fe84a72a2d9f59806c40f5029610466b414b1..bcf27c5f3146488bb98b38c20352b1e3e39a7379 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Article.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Article.php
@@ -299,7 +299,6 @@ class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wr
         ->setText($this->_eventsText($end))
         ->setClass('badge_event_end');
 
-
     $period = new Class_Article_EventTimingPeriod($this->_model);
     $period->startEndDo(function($start, $end) use (&$badges) {
       $badges []= (new Intonation_Library_Badge)
@@ -312,17 +311,20 @@ class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wr
   }
 
 
-  protected function _eventsText($time) {
-    $time = strtotime($time);
-    return $this->_model->getAllDay()
-      ? $this->_shortDate($time)
+  protected function _eventsText(string $time) : string {
+    $timestamp = strtotime($time);
+
+    return ($this->_model->getAllDay()
+            || ' 00:00' == substr($time, -6)
+            || ' 00:00:00' == substr($time, -9))
+      ? $this->_shortDate($timestamp)
       : $this->_('%s à %s',
-                 $this->_shortDate($time),
-                 strftime($this->_('%H:%M'), $time));
+                 $this->_shortDate($timestamp),
+                 strftime($this->_('%H:%M'), $timestamp));
   }
 
 
-  protected function _shortDate($time) {
+  protected function _shortDate(int $time) : string {
     return strftime($this->_('%d/%m/%Y'), $time);
   }
 
diff --git a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsViewTest.php b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsViewTest.php
index 80100f26893e8888007513e3e1c403cde8945199..8ebd3a963caea93c67c12e21997bee7e414fd1ee 100644
--- a/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsViewTest.php
+++ b/tests/scenarios/ArticlesMultipleTimings/ArticlesMultipleTimingsViewTest.php
@@ -40,13 +40,21 @@ abstract class ArticlesMultipleTimingsViewTestCase extends AbstractControllerTes
                                        'start' => '2021-06-01 10:00:00',
                                        'end' => '2021-06-01 11:00:00']))
       ->addEventTiming($this->fixture(Class_Article_EventTiming::class,
-                                      ['id' => 1,
+                                      ['id' => 2,
                                        'start' => '2021-06-08 10:00:00',
                                        'end' => '2021-06-08 11:00:00']))
       ->addEventTiming($this->fixture(Class_Article_EventTiming::class,
-                                      ['id' => 1,
+                                      ['id' => 3,
                                        'start' => '2021-06-15 10:00:00',
                                        'end' => '2021-06-15 11:00:00']))
+      ->addEventTiming($this->fixture(Class_Article_EventTiming::class,
+                                      ['id' => 4,
+                                       'start' => '2021-06-12 00:00:00',
+                                       'end' => '2021-06-12 23:59:00']))
+      ->addEventTiming($this->fixture(Class_Article_EventTiming::class,
+                                      ['id' => 5,
+                                       'start' => '2021-06-13',
+                                       'end' => '2021-06-13 23:59:00']))
       ->assertSave();
 
     $this->fixture(Class_ArticleCategorie::class,
@@ -54,9 +62,9 @@ abstract class ArticlesMultipleTimingsViewTestCase extends AbstractControllerTes
                     'libelle' => 'Agenda',
                     'articles' => [$heure_du_conte]]);
 
-    Storm_Test_ObjectWrapper::onLoaderOfModel(Class_Article::class)
-      ->whenCalled('getArticlesByPreferences')
-      ->answers([$heure_du_conte]);
+    $this->onLoaderOfModel(Class_Article::class)
+         ->whenCalled('getArticlesByPreferences')
+         ->answers([$heure_du_conte]);
 
     $time_source = new TimeSourceForTest('2021-06-08 09:00:00');
     Class_Article_EventTiming::setTimeSource($time_source);
@@ -72,7 +80,7 @@ abstract class ArticlesMultipleTimingsViewTestCase extends AbstractControllerTes
 
 
 
-class ArticlesMultipleTimingsViewTest extends ArticlesMultipleTimingsViewTestCase {
+class ArticlesMultipleTimingsViewHistoricTest extends ArticlesMultipleTimingsViewTestCase {
   public function setUp() {
     parent::setUp();
     $this->dispatch('/cms/articleview/id/5');
@@ -99,6 +107,34 @@ class ArticlesMultipleTimingsViewTest extends ArticlesMultipleTimingsViewTestCas
   }
 
 
+  /** @test */
+  public function timingsShouldContainsSamediDouzeJuin() {
+    $this->assertXPathContentContains('//div[@class="article_timings"]/ul/li',
+                                      'samedi 12 juin 2021');
+  }
+
+
+  /** @test */
+  public function timingsShouldNotContainsSamediDouzeJuinAMinuit() {
+    $this->assertNotXPathContentContains('//div[@class="article_timings"]/ul/li',
+                                         'samedi 12 juin 2021 à 00:00');
+  }
+
+
+  /** @test */
+  public function timingsShouldContainsDimancheTreizeJuin() {
+    $this->assertXPathContentContains('//div[@class="article_timings"]/ul/li',
+                                      'dimanche 13 juin 2021');
+  }
+
+
+  /** @test */
+  public function timingsShouldNotContainsDimancheTreizeJuinAMinuit() {
+    $this->assertNotXPathContentContains('//div[@class="article_timings"]/ul/li',
+                                         'dimanche 13 juin 2021 à 00:00');
+  }
+
+
   /** @test */
   public function timingsShouldNotContainsPremierJuinDeDixAOnzeHeures() {
     $this->assertNotXPathContentContains('//div[@class="article_timings"]/ul/li',
@@ -109,7 +145,7 @@ class ArticlesMultipleTimingsViewTest extends ArticlesMultipleTimingsViewTestCas
 
 
 
-class ArticlesMultipleTimingsTemplatesViewTest extends ArticlesMultipleTimingsViewTestCase {
+class ArticlesMultipleTimingsViewTemplatesTest extends ArticlesMultipleTimingsViewTestCase {
   public function setUp() {
     parent::setUp();
     $this->_buildTemplateProfil(['id' => 4,
diff --git a/tests/scenarios/Templates/TemplatesAgendaTest.php b/tests/scenarios/Templates/TemplatesAgendaTest.php
index 230a651c26655c518b5b1e82e5dd6f85c0ca8675..6ea023e7b9be08d273204974681423d9618f1cfb 100644
--- a/tests/scenarios/Templates/TemplatesAgendaTest.php
+++ b/tests/scenarios/Templates/TemplatesAgendaTest.php
@@ -635,3 +635,47 @@ class TemplatesAgendaWallModeSelectedMonthNextMonthNoEventTest
                                       'Aucun événement en décembre 2021 ni les mois suivants');
   }
 }
+
+
+
+
+class TemplatesAgendaWallModeSelectedMonthIsCurrentMonthArticleWithoutEndDateTest
+  extends TemplatesAgendaWallModeDateFilterTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->_french
+      ->setEventsFin('')
+      ->setDateFin('')
+      ->save();
+
+    Class_Article::getLoader()
+      ->whenCalled('getArticlesByPreferences') // all published events from selected month
+      ->with(['display_order' => 'EventDebut',
+              'id_categorie' => '',
+              'events_only' => true,
+              'event_date' => '2021-11',
+              'id_bib' => 0,
+              'id_lieu' => '',
+              'custom_fields' => [],
+              'published' => true])
+      ->answers([ $this->_french ])
+
+      ->beStrict();
+
+    $this->dispatch('/opac/cms/calendar/widget_id/1/profile_id/78/date/2021-11');
+  }
+
+
+  /** @test */
+  public function parlezVousFrançaisShouldBePresent() {
+    $this->assertXPathContentContains('//div[@class="calendar"]//a', 'Parlez-vous français ?');
+  }
+
+
+  /** @test */
+  public function heureShouldNotBePresent() {
+    $this->assertNotXPathContentContains('//div[@class="calendar"]//span', 'à 00:00');
+  }
+}