diff --git a/app/but/jury_but.py b/app/but/jury_but.py
index a7a37ab6b04cf7680caf27d720d485df7e4f1795..3c1e1b189945982fbe39204fa34bbab915dbd004 100644
--- a/app/but/jury_but.py
+++ b/app/but/jury_but.py
@@ -526,7 +526,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
         return formsemestre.annee_scolaire()
 
     def annee_scolaire_str(self) -> str:
-        "L'année scolaire, eg '2021 - 2022'"
+        "L'année scolaire, eg '2021 - 2022' ou '2021' en hémisphère sud"
         formsemestre = self.formsemestre_impair or self.formsemestre_pair
         return formsemestre.annee_scolaire_str().replace(" ", "")
 
diff --git a/app/models/config.py b/app/models/config.py
index f137ccccbaadc919b33eada0d19495e545734708..e869a93ac9f074a6ef7c073ead9d817deeafa89e 100644
--- a/app/models/config.py
+++ b/app/models/config.py
@@ -355,7 +355,9 @@ class ScoDocSiteConfig(models.ScoDocModel):
 
     @classmethod
     def get_month_debut_periode2(cls) -> int:
-        """Mois de début de l'année scolaire."""
+        """Mois de début de la seconde période (semestre) de l'année.
+        Par défaut, 12 (décembre). Sera souvent juillet en hémisphère sud.
+        """
         return cls._get_int_field("month_debut_periode2", scu.MONTH_DEBUT_PERIODE2)
 
     @classmethod
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index dc08a847ba99fb1343c2659572585825aaebf544..7e0eb1b7f27f247e36e17f0b9699e8c5b5a649d9 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -699,18 +699,27 @@ class FormSemestre(models.ScoDocModel):
         """
         if self.semestre_id <= 0:
             return False  # formations sans semestres
+        # août (8) en métropole, janvier (1) en hémisphère sud:
+        month_debut = ScoDocSiteConfig.get_month_debut_annee_scolaire()
+        if month_debut < 4:
+            # Hémisphère sud: utilise date début deuxième période
+            # typiquement juillet
+            pivot = ScoDocSiteConfig.get_month_debut_periode2()
+            return (
+                # impair commençaant en fin d'année civile
+                (self.semestre_id % 2 and self.date_debut.month >= pivot)
+                or
+                # pair commençant en début d'année civile
+                ((not self.semestre_id % 2) and self.date_debut.month < pivot)
+            )
+
+        # Hémisphère nord
         return (
             # impair
-            (
-                self.semestre_id % 2
-                and self.date_debut.month < scu.MONTH_DEBUT_ANNEE_SCOLAIRE
-            )
+            (self.semestre_id % 2 and self.date_debut.month < month_debut)
             or
             # pair
-            (
-                (not self.semestre_id % 2)
-                and self.date_debut.month >= scu.MONTH_DEBUT_ANNEE_SCOLAIRE
-            )
+            ((not self.semestre_id % 2) and self.date_debut.month >= month_debut)
         )
 
     @classmethod
@@ -719,8 +728,8 @@ class FormSemestre(models.ScoDocModel):
         date_debut: datetime.date,
         year=False,
         periode=None,
-        mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
-        mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
+        mois_pivot_annee: int | None = None,
+        mois_pivot_periode: int | None = None,
     ) -> bool:
         """Vrai si la date_debut est dans la période indiquée (1,2,0)
         du semestre `periode` de l'année scolaire indiquée
@@ -734,6 +743,10 @@ class FormSemestre(models.ScoDocModel):
         """
         if not year:
             year = scu.annee_scolaire()
+        if mois_pivot_annee is None:
+            mois_pivot_annee = ScoDocSiteConfig.get_month_debut_annee_scolaire()
+        if mois_pivot_periode is None:
+            mois_pivot_periode = ScoDocSiteConfig.get_month_debut_periode2()
         # n'utilise pas le jour pivot
         jour_pivot_annee = jour_pivot_periode = 1
         # calcule l'année universitaire et la période
@@ -758,10 +771,10 @@ class FormSemestre(models.ScoDocModel):
     def comp_periode(
         cls,
         date_debut: datetime,
-        mois_pivot_annee=scu.MONTH_DEBUT_ANNEE_SCOLAIRE,
-        mois_pivot_periode=scu.MONTH_DEBUT_PERIODE2,
-        jour_pivot_annee=1,
-        jour_pivot_periode=1,
+        mois_pivot_annee: int | None = None,
+        mois_pivot_periode: int | None = None,
+        jour_pivot_annee: int = 1,
+        jour_pivot_periode: int = 1,
     ) -> tuple[int, int]:
         """Calcule la session associée à un formsemestre commençant en date_debut
         sous la forme (année, période)
@@ -782,6 +795,10 @@ class FormSemestre(models.ScoDocModel):
         pp < pa       -----------------|-------------------|---------------->
                         (A-1,  P:1)   pp     (A-1, P:2)   pa    (A, P:1)
         """
+        if mois_pivot_annee is None:
+            mois_pivot_annee = ScoDocSiteConfig.get_month_debut_annee_scolaire()
+        if mois_pivot_periode is None:
+            mois_pivot_periode = ScoDocSiteConfig.get_month_debut_periode2()
         pivot_annee = 100 * mois_pivot_annee + jour_pivot_annee
         pivot_periode = 100 * mois_pivot_periode + jour_pivot_periode
         pivot_sem = 100 * date_debut.month + date_debut.day
@@ -930,7 +947,7 @@ class FormSemestre(models.ScoDocModel):
         return scu.annee_scolaire_debut(self.date_debut.year, self.date_debut.month)
 
     def annee_scolaire_str(self):
-        "2021 - 2022"
+        """2021 - 2022 (ou "2021" si hémisphère sud)"""
         return scu.annee_scolaire_repr(self.date_debut.year, self.date_debut.month)
 
     def mois_debut(self) -> str:
diff --git a/app/scodoc/codes_cursus.py b/app/scodoc/codes_cursus.py
index e796b9b403eb361ab76b45635479a9964d5ea790..3c4e6d155dcaf27b5a936b2ebcc4bbc6fc34318e 100644
--- a/app/scodoc/codes_cursus.py
+++ b/app/scodoc/codes_cursus.py
@@ -778,7 +778,7 @@ class CursusMasterLMD(TypeCursus):
     TYPE_CURSUS = CodesCursus.MasterLMD
     NAME = "Master LMD"
     NB_SEM = 4
-    COMPENSATION_UE = True  # variabale inutilisée
+    COMPENSATION_UE = True  # variable inutilisée
     UNUSED_CODES = set((ADC, ATT, ATB))
 
 
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index 25245424edede1cc8a2ea88d1160dba940b89588..27ece1354d8c23b6e8239c0399f5f822b61c3478 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -1429,13 +1429,23 @@ def timedate_human_repr():
 
 
 def annee_scolaire_repr(year, month):
-    """representation de l'annee scolaire : '2009 - 2010'
+    """Représentation de l'annee scolaire : '2009 - 2010'
     à partir d'une date.
+    Dans l'hémisphère sud, l'année scolaire coincide avec l'année civile.
+    On considère que si le mois de début de l'année scolaire est au
+    premier trimestre (jan-fev-mar), alors l'affichage n'indique que l'année
+    en cours (eg "2024").
     """
-    if month >= MONTH_DEBUT_ANNEE_SCOLAIRE:  # apres le 1er aout
+    from app.models.config import ScoDocSiteConfig
+
+    month_debut = ScoDocSiteConfig.get_month_debut_annee_scolaire()
+    if month_debut < 4:
+        # Hémisphère sud:
+        return str(year) if month >= month_debut else str(year - 1)
+    # Hémisphère nord
+    if month >= month_debut:  # par ex. apres le 1er aout
         return f"{year} - {year + 1}"
-    else:
-        return f"{year - 1} - {year}"
+    return f"{year - 1} - {year}"
 
 
 def annee_scolaire() -> int:
@@ -1450,10 +1460,12 @@ def annee_scolaire_debut(year, month) -> int:
     Par défaut (hémisphère nord), l'année du mois de août
     précédent la date indiquée.
     """
-    if int(month) >= MONTH_DEBUT_ANNEE_SCOLAIRE:
+    from app.models.config import ScoDocSiteConfig
+
+    month_debut = ScoDocSiteConfig.get_month_debut_annee_scolaire()
+    if int(month) >= month_debut:
         return int(year)
-    else:
-        return int(year) - 1
+    return int(year) - 1
 
 
 def date_debut_annee_scolaire(annee_sco: int | None = None) -> datetime.datetime:
@@ -1461,11 +1473,15 @@ def date_debut_annee_scolaire(annee_sco: int | None = None) -> datetime.datetime
     Si annee_sco n'est pas spécifié, année courante
     (par défaut, l'année scolaire en métropole commence le 1er aout)
     """
+    from app.models.config import ScoDocSiteConfig
+
     if annee_sco is None:
         annee_sco = annee_scolaire()
     try:
         return datetime.datetime(
-            year=annee_sco, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1
+            year=annee_sco,
+            month=ScoDocSiteConfig.get_month_debut_annee_scolaire(),
+            day=1,
         )
     except ValueError as exc:
         raise ScoValueError("année scolaire invalide") from exc
@@ -1478,11 +1494,15 @@ def date_fin_annee_scolaire(annee_sco: int | None = None) -> datetime.datetime:
     # on prend la date de début de l'année scolaire suivante,
     # et on lui retire 1 jour.
     # On s'affranchit ainsi des problèmes de durées de mois.
+    from app.models.config import ScoDocSiteConfig
+
     if annee_sco is None:
         annee_sco = annee_scolaire()
     try:
         return datetime.datetime(
-            year=annee_sco + 1, month=MONTH_DEBUT_ANNEE_SCOLAIRE, day=1
+            year=annee_sco + 1,
+            month=ScoDocSiteConfig.get_month_debut_annee_scolaire(),
+            day=1,
         ) - datetime.timedelta(days=1)
     except (TypeError, ValueError) as exc:
         raise ScoValueError("année scolaire invalide") from exc
diff --git a/tests/unit/test_periode.py b/tests/unit/test_periode.py
index f32d6ebea981d35bcf705c4070a1b7d5e7d3c0eb..490b1a5c093e553dffa59f77af3735aa52f4a1ec 100644
--- a/tests/unit/test_periode.py
+++ b/tests/unit/test_periode.py
@@ -3,7 +3,7 @@
 """Test Periodes
 
 Utiliser comme:
-    pytest tests/unit/test_periode.py
+    pytest tests/unit/_test_periode.py
 
 Calcule la session associée à un formsemestre sous la forme (année, période)
 année: première année de l'année scolaire
@@ -32,8 +32,30 @@ import datetime
 from app.models import FormSemestre
 from app.scodoc.sco_formsemestre import sem_in_semestre_scolaire
 
-
-def test_default():
+# Nota: pour accélerer (éviter de recrer l'app),
+# on regroupe ces petits tests dans une seule fonction
+
+
+def test_periode(test_client):
+    "Joue tous les tests de ce module"
+    _test_default()
+    _test_automne_nord()
+    _test_noel_nord()
+    _test_ete_nord()
+    _test_printemps_sud()
+    _test_automne_sud()
+    _test_noel_sud()
+    _test_ete_sud()
+    _test_nouvel_an_sud()
+    _test_nouvel_an_special_pp_before_pa()
+    _test_nouvel_ete_pp_before_pa()
+    _test_automne_special_pp_before_pa()
+    _test_sem_in_periode1_default()
+    _test_sem_in_periode2_default()
+    _test_sem_in_annee_default()
+
+
+def _test_default():
     # with default
     assert (2021, 2) == FormSemestre.comp_periode(datetime.datetime(2022, 1, 1))
     assert (2021, 2) == FormSemestre.comp_periode(
@@ -41,59 +63,59 @@ def test_default():
     )
 
 
-def test_automne_nord():
+def _test_automne_nord():
     assert (2022, 1) == FormSemestre.comp_periode(datetime.datetime(2022, 9, 1))
 
 
-def test_noel_nord():
+def _test_noel_nord():
     assert (2022, 2) == FormSemestre.comp_periode(datetime.datetime(2022, 12, 15))
 
 
-def test_ete_nord():
+def _test_ete_nord():
     assert (2021, 2) == FormSemestre.comp_periode(datetime.datetime(2022, 7, 30))
 
 
-def test_printemps_sud():
+def _test_printemps_sud():
     assert (2022, 1) == FormSemestre.comp_periode(
         datetime.datetime(2022, 1, 1), 1, 1, 1, 8
     )
 
 
-def test_automne_sud():
+def _test_automne_sud():
     assert (2022, 2) == FormSemestre.comp_periode(
         datetime.datetime(2022, 8, 2), 1, 8, 1, 1
     )
 
 
-def test_noel_sud():
+def _test_noel_sud():
     assert (2022, 2) == FormSemestre.comp_periode(
         datetime.datetime(2022, 12, 30), 1, 8, 1, 1
     )
 
 
-def test_ete_sud():
+def _test_ete_sud():
     assert (2022, 1) == FormSemestre.comp_periode(
         datetime.datetime(2022, 7, 30), 1, 8, 1, 1
     )
 
 
-def test_nouvel_an_sud():
+def _test_nouvel_an_sud():
     assert (2021, 2) == FormSemestre.comp_periode(
         datetime.datetime(2022, 1, 1), 3, 8, 1, 1
     )
 
 
-def test_nouvel_an_special_pp_before_pa():
+def _test_nouvel_an_special_pp_before_pa():
     assert (2023, 1) == FormSemestre.comp_periode(
         datetime.datetime(2024, 1, 10), 8, 2, 1, 1
     )
 
 
-def test_nouvel_ete_pp_before_pa():
+def _test_nouvel_ete_pp_before_pa():
     assert (2023, 2) == FormSemestre.comp_periode(datetime.datetime(2024, 6, 1), 8, 2)
 
 
-def test_automne_special_pp_before_pa():
+def _test_automne_special_pp_before_pa():
     assert (2024, 1) == FormSemestre.comp_periode(datetime.datetime(2024, 9, 20), 8, 2)
 
 
@@ -105,7 +127,7 @@ sem_next_year = {"date_debut_iso": "2023-08-16"}
 sem_prev_year = {"date_debut_iso": "2022-07-31"}
 
 
-def test_sem_in_periode1_default():
+def _test_sem_in_periode1_default():
     assert True is sem_in_semestre_scolaire(sem_automne, 2022, 1)
     assert False is sem_in_semestre_scolaire(sem_nouvel_an, 2022, 1)
     assert False is sem_in_semestre_scolaire(sem_printemps, 2022, 1)
@@ -114,7 +136,7 @@ def test_sem_in_periode1_default():
     assert False is sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
 
 
-def test_sem_in_periode2_default():
+def _test_sem_in_periode2_default():
     assert False is sem_in_semestre_scolaire(sem_automne, 2022, 2)
     assert True is sem_in_semestre_scolaire(sem_nouvel_an, 2022, 2)
     assert True is sem_in_semestre_scolaire(sem_printemps, 2022, 2)
@@ -123,7 +145,7 @@ def test_sem_in_periode2_default():
     assert False is sem_in_semestre_scolaire(sem_prev_year, 2022, 1)
 
 
-def test_sem_in_annee_default():
+def _test_sem_in_annee_default():
     assert True is sem_in_semestre_scolaire(sem_automne, 2022, 0)
     assert True is sem_in_semestre_scolaire(sem_nouvel_an, 2022)
     assert True is sem_in_semestre_scolaire(sem_printemps, 2022, 0)