diff --git a/migrations/04_closing_time.sql b/migrations/04_closing_time.sql
new file mode 100644
index 0000000..eaceb74
--- /dev/null
+++ b/migrations/04_closing_time.sql
@@ -0,0 +1,5 @@
+CREATE TABLE closing_time (
+    id SERIAL PRIMARY KEY,
+    from_date DATE,
+    to_date DATE
+)
\ No newline at end of file
diff --git a/src/backend/data.rs b/src/backend/data.rs
index fef715c..b23ae2c 100644
--- a/src/backend/data.rs
+++ b/src/backend/data.rs
@@ -348,7 +348,8 @@ impl ResProperty {
 pub struct PublicFormData {
     pub property: ResProperty,
     pub hours: Vec<DayHour>,
-    pub reservations: Vec<Reservation>
+    pub reservations: Vec<Reservation>,
+    pub closing_days: Option<ClosingTime>
 }
 
 fn empty_slots() -> Vec<String> {
@@ -637,3 +638,27 @@ impl Appearance {
         self.id
     }
 }
+
+pub fn validate_closing_time(time: &ClosingTime) -> Result<(), ValidationError> {
+    if time.from_date > time.to_date {
+        let mut err = ValidationError::new("to date in past");
+        err.message = Some("To date must be after from date".into());
+        Err(err)
+    } else {
+        Ok(())
+    }
+}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize, Validate, Eq, PartialEq)]
+#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
+#[validate(schema(function = "validate_closing_time"))]
+pub struct ClosingTime {
+    id: i32,
+    pub from_date: NaiveDate,
+    pub to_date: NaiveDate
+}
+impl ClosingTime {
+    pub fn id(&self) -> i32 {
+        self.id
+    }
+}
diff --git a/src/backend/opening_hours.rs b/src/backend/opening_hours.rs
index 1c6d070..0a499b7 100644
--- a/src/backend/opening_hours.rs
+++ b/src/backend/opening_hours.rs
@@ -3,7 +3,7 @@ use cfg_if::cfg_if;
 use chrono::Weekday;
 use leptos::*;
 use validator::Validate;
-use crate::backend::data::{ApiResponse, DayHour, WeekHours};
+use crate::backend::data::{ApiResponse, ClosingTime, DayHour, WeekHours};
 use crate::components::data_form::ForValidation;
 
 cfg_if! { if #[cfg(feature = "ssr")] {
@@ -89,4 +89,70 @@ impl ForValidation for UpdateHours {
     fn entity(&self) -> &dyn Validate {
         &self.hours
     }
+}
+
+#[server]
+pub async fn get_closing_time() -> Result<Option<ClosingTime>, ServerFnError> {
+    use crate::backend::get_pool;
+    use sqlx::{Error, query_as};
+
+    let pool = get_pool().await?;
+    let ct = query_as::<_, ClosingTime>("SELECT * FROM closing_time")
+        .fetch_one(&pool)
+        .await;
+
+    Ok(if let Err(ref e) = ct {
+        if matches!(e, Error::RowNotFound) {
+            None
+        } else {
+            Some(ct?)
+        }
+    } else {
+        Some(ct?)
+    })
+}
+
+#[server]
+pub async fn update_closing_time(time: ClosingTime) -> Result<ApiResponse<()>, ServerFnError> {
+    use crate::perm_check;
+    use crate::backend::get_pool;
+
+    perm_check!(is_admin);
+
+    let pool = get_pool().await?;
+    let mut tx = pool.begin().await?;
+
+    sqlx::query("DELETE FROM closing_time")
+        .execute(&mut *tx)
+        .await?;
+    sqlx::query("INSERT INTO closing_time(from_date, to_date) VALUES($1, $2)")
+        .bind(time.from_date)
+        .bind(time.to_date)
+        .execute(&mut *tx)
+        .await?;
+
+    tx.commit().await?;
+
+    Ok(ApiResponse::Data(()))
+}
+
+impl ForValidation for UpdateClosingTime {
+    fn entity(&self) -> &dyn Validate {
+        &self.time
+    }
+}
+
+#[server]
+pub async fn delete_closing_time() -> Result<ApiResponse<()>, ServerFnError> {
+    use crate::perm_check;
+    use crate::backend::get_pool;
+
+    perm_check!(is_admin);
+
+    let pool = get_pool().await?;
+    sqlx::query("DELETE FROM closing_time")
+        .execute(&pool)
+        .await?;
+
+    Ok(ApiResponse::Data(()))
 }
\ No newline at end of file
diff --git a/src/backend/reservation.rs b/src/backend/reservation.rs
index fe47407..035c9e7 100644
--- a/src/backend/reservation.rs
+++ b/src/backend/reservation.rs
@@ -26,6 +26,7 @@ cfg_if! { if #[cfg(feature = "ssr")] {
     use crate::backend::user::emails_for_notify;
     use crate::locales::trl;
     use rust_decimal::prelude::ToPrimitive;
+    use crate::backend::opening_hours::get_closing_time;
 
     async fn find_sum_by_uuid(uuid: &Uuid, tx: &mut Transaction<'_, Postgres>) -> Result<ReservationSum, Error> {
         let reservation = query_as::<_, ReservationSum>("SELECT * FROM reservation_sum WHERE uuid = $1")
@@ -240,13 +241,15 @@ pub async fn get_public_form_data(day: NaiveDate) -> Result<ApiResponse<Vec<Publ
     let hours = hours_for_day(day.weekday()).await?;
     let props = get_props(Some("active = true")).await?;
     let reservations = reservations_for_day(&day).await?;
+    let closing_days = get_closing_time().await?;
 
     info!("Loading public form data");
 
     Ok(ApiResponse::Data(props.into_iter().map(|p| PublicFormData {
         property: p,
         hours: hours.clone(),
-        reservations: reservations.clone()
+        reservations: reservations.clone(),
+        closing_days: closing_days.clone()
     }).collect::<Vec<_>>()))
 }
 
diff --git a/src/locales/catalogues.rs b/src/locales/catalogues.rs
index c6b4472..37f4eca 100644
--- a/src/locales/catalogues.rs
+++ b/src/locales/catalogues.rs
@@ -158,6 +158,10 @@ lazy_static! {
                 ("October", "Říjen"),
                 ("November", "Listpopad"),
                 ("December", "Prosinec"),
+                ("Closing days: ", "Zavírací dny: "),
+                ("Closing days", "Zavírací dny"),
+                ("From", "Od"),
+                ("To", "do")
             ])),
             ("sk", HashMap::from( [
                 ("Dashboard", "Prehlad"),
diff --git a/src/pages/hours_edit.rs b/src/pages/hours_edit.rs
index c4d4af6..e05e6d7 100644
--- a/src/pages/hours_edit.rs
+++ b/src/pages/hours_edit.rs
@@ -1,7 +1,8 @@
+use chrono::Local;
 use leptos::*;
 use crate::backend::data::WeekHours;
-use crate::backend::opening_hours::UpdateHours;
-use crate::components::data_form::DataForm;
+use crate::backend::opening_hours::{DeleteClosingTime, UpdateClosingTime, UpdateHours};
+use crate::components::data_form::{DataForm, QuestionDialog};
 use crate::components::modal_box::DialogOpener;
 use crate::locales::trl;
 
@@ -27,4 +28,46 @@ pub fn EditHours(opener: DialogOpener, hours: ReadSignal<WeekHours>) -> impl Int
             </div>
         </DataForm>
     }
+}
+
+#[component]
+pub fn closing_days(opener: DialogOpener) -> impl IntoView {
+    let update_days = create_server_action::<UpdateClosingTime>();
+
+    view! {
+        <DataForm opener=opener action=update_days title="Closing days">
+            <input type="hidden" value=0 name="time[id]"/>
+            <div class="row">
+                <div class="col mb-3">
+                    <label  for="from_day" class="form-label">{trl("From")}</label>
+                    <input
+                        type="date"
+                        id="from_day"
+                        class="form-control"
+                        prop:value={move || Local::now().date_naive().format("%Y-%m-%d").to_string()}
+                        name="time[from_date]"
+                    />
+                    <label  for="to_day" class="form-label">{trl("To")}</label>
+                    <input
+                        type="date"
+                        id="to_day"
+                        class="form-control"
+                        prop:value={move || Local::now().date_naive().format("%Y-%m-%d").to_string()}
+                        name="time[to_date]"
+                    />
+                </div>
+            </div>
+        </DataForm>
+    }
+}
+
+#[component]
+pub fn del_closing_days(opener: DialogOpener) -> impl IntoView {
+    let delete = create_server_action::<DeleteClosingTime>();
+
+    view! {
+        <QuestionDialog opener=opener action=delete title="Delete closing days">
+            <div>{trl("Are you sure you want to delete closing days?")}</div>
+        </QuestionDialog>
+    }
 }
\ No newline at end of file
diff --git a/src/pages/opening_hours.rs b/src/pages/opening_hours.rs
index 247bf23..8dd7064 100644
--- a/src/pages/opening_hours.rs
+++ b/src/pages/opening_hours.rs
@@ -1,10 +1,10 @@
 use chrono::Weekday;
 use leptos::*;
 use crate::backend::data::{DayHours, WeekHours};
-use crate::backend::opening_hours::get_hours;
+use crate::backend::opening_hours::{get_closing_time, get_hours};
 use crate::components::modal_box::DialogOpener;
-use crate::locales::{show_day, trl};
-use crate::pages::hours_edit::EditHours;
+use crate::locales::{loc_date, show_day, trl};
+use crate::pages::hours_edit::{ClosingDays, DelClosingDays, EditHours};
 
 fn show_time(tm: &str) -> impl Fn() -> String {
     if tm.is_empty() {
@@ -17,11 +17,16 @@ fn show_time(tm: &str) -> impl Fn() -> String {
 #[component]
 pub fn OpeningHours() -> impl IntoView {
     let editor = DialogOpener::new();
+    let closing_editor = DialogOpener::new();
+    let closing_delete = DialogOpener::new();
     let hours = create_blocking_resource(move || editor.visible(), move |_| {get_hours()});
+    let closing_days = create_blocking_resource(move || closing_editor.visible() | closing_delete.visible(), move |_| get_closing_time());
     let hrs = create_rw_signal(WeekHours::default());
 
     view! {
         <EditHours opener=editor hours=hrs.read_only() />
+        <ClosingDays opener=closing_editor/>
+        <DelClosingDays opener=closing_delete/>
         <div class="card mb-3">
             <div class="card-body">
                 <h5 class="card-title"><i class="bx bxs-watch"></i>" "{trl("Opening hours")}</h5>
@@ -63,6 +68,28 @@ pub fn OpeningHours() -> impl IntoView {
                         }}
                     </Transition>
                 </p>
+                <div align="center">
+                    {trl("Closing days: ")}
+                    <Transition fallback=move || view! {<p>{trl("Loading...")}</p> }>
+                    {
+                        closing_days.get().map(|cd| match cd {
+                        Ok(cd) => {
+                            if let Some(cd) = cd {
+                                view! {<p>{loc_date(cd.from_date)}" - "{loc_date(cd.to_date)}</p>}
+                            } else {
+                                view! {<p></p>}
+                            }
+                        }
+                        Err(_) => {view! {<p></p>}}})
+                    }
+                    </Transition>
+                    <a href="javascript:void(0)" class="card-link" on:click = move |_| {
+                            closing_editor.show();
+                         }><i class="bx bx-edit-alt me-1"></i></a>
+                    <a class="card-link text-danger" href="javascript:void(0);" on:click=move |_| {
+                            closing_delete.show();
+                        }><i class="bx bx-trash me-1"></i> </a>
+                </div>
             </div>
         </div>
     }
diff --git a/src/pages/public.rs b/src/pages/public.rs
index 41cd715..a4c1ef1 100644
--- a/src/pages/public.rs
+++ b/src/pages/public.rs
@@ -5,7 +5,7 @@ use leptos_router::*;
 use rust_decimal::Decimal;
 use crate::backend::appearance::get_appearance;
 use crate::backend::customer::get_remembered;
-use crate::backend::data::{ApiResponse, Customer, DayHour, Reservation, ResProperty, SlotType, TmCheck};
+use crate::backend::data::{ApiResponse, ClosingTime, Customer, DayHour, Reservation, ResProperty, SlotType, TmCheck};
 use crate::backend::reservation::{CreateReservation, get_public_form_data, is_reserved};
 use crate::backend::user::get_pow;
 use crate::components::data_form::ForValidation;
@@ -20,51 +20,62 @@ fn time_selector(
     reservations: Vec<Reservation>,
     property: ResProperty,
     slots: RwSignal<Vec<String>>,
-    price: RwSignal<Decimal>) -> impl IntoView {
-    let checks = hours.into_iter().map(|h| {
-        match property.slot {
-            SlotType::Quarter => {
-                let mut ret: Vec<TmCheck> = vec![];
-                logging::log!("quarter");
-                for n in 0..(h.to() - h.from()).num_minutes() * 4 / 60 {
-                    ret.push(TmCheck {
-                        from: h.from() + Duration::minutes(n * 15),
-                        to: h.from() + Duration::minutes((n + 1) * 15)
-                    });
+    price: RwSignal<Decimal>,
+    day: ReadSignal<NaiveDate>,
+    closing_days: Option<ClosingTime>) -> impl IntoView {
+    let closed = if let Some(c) = closing_days {
+        day.get() >= c.from_date && day.get() <= c.to_date
+    } else {
+        false
+    };
+    let checks = if !closed {
+        hours.into_iter().map(|h| {
+            match property.slot {
+                SlotType::Quarter => {
+                    let mut ret: Vec<TmCheck> = vec![];
+                    logging::log!("quarter");
+                    for n in 0..(h.to() - h.from()).num_minutes() * 4 / 60 {
+                        ret.push(TmCheck {
+                            from: h.from() + Duration::minutes(n * 15),
+                            to: h.from() + Duration::minutes((n + 1) * 15)
+                        });
+                    }
+                    ret
                 }
-                ret
-            }
-            SlotType::Half => {
-                let mut ret: Vec<TmCheck> = vec![];
-                logging::log!("half");
-                for n in 0..(h.to() - h.from()).num_minutes() * 2 / 60 {
-                    ret.push(TmCheck {
-                        from: h.from() + Duration::minutes(n * 30),
-                        to: h.from() + Duration::minutes((n + 1) * 30)
-                    });
+                SlotType::Half => {
+                    let mut ret: Vec<TmCheck> = vec![];
+                    logging::log!("half");
+                    for n in 0..(h.to() - h.from()).num_minutes() * 2 / 60 {
+                        ret.push(TmCheck {
+                            from: h.from() + Duration::minutes(n * 30),
+                            to: h.from() + Duration::minutes((n + 1) * 30)
+                        });
+                    }
+                    ret
                 }
-                ret
-            }
-            SlotType::Hour => {
-                let mut ret: Vec<TmCheck> = vec![];
-                for n in 0..(h.to() - h.from()).num_minutes() / 60 {
+                SlotType::Hour => {
+                    let mut ret: Vec<TmCheck> = vec![];
+                    for n in 0..(h.to() - h.from()).num_minutes() / 60 {
+                        ret.push(TmCheck {
+                            from: h.from() + Duration::minutes(n * 60),
+                            to: h.from() + Duration::minutes((n + 1) * 60)
+                        });
+                    }
+                    ret
+                }
+                SlotType::Day => {
+                    let mut ret: Vec<TmCheck> = vec![];
                     ret.push(TmCheck {
-                        from: h.from() + Duration::minutes(n * 60),
-                        to: h.from() + Duration::minutes((n + 1) * 60)
+                        from: NaiveTime::from_hms_opt(0, 0, 0).unwrap(),
+                        to: NaiveTime::from_hms_opt(23, 59, 59).unwrap()
                     });
+                    ret
                 }
-                ret
-            }
-            SlotType::Day => {
-                let mut ret: Vec<TmCheck> = vec![];
-                ret.push(TmCheck {
-                    from: NaiveTime::from_hms_opt(0,0,0).unwrap(),
-                    to: NaiveTime::from_hms_opt(23, 59, 59).unwrap()
-                });
-                ret
             }
-        }
-    }).collect::<Vec<_>>().into_iter().flatten().collect::<Vec<_>>();
+        }).collect::<Vec<_>>().into_iter().flatten().collect::<Vec<_>>()
+    } else {
+        vec![]
+    };
 
     let prop_id = property.id();
     let closed = checks.is_empty();
@@ -222,6 +233,8 @@ pub fn Public() -> impl IntoView {
                                                     hours={data.hours.clone()}
                                                     reservations={data.reservations.clone()}
                                                     property={data.property.clone()}
+                                                    day={day.read_only()}
+                                                    closing_days={data.closing_days.clone()}
                                                     slots={slots}
                                                     price={price}/>
                                             </div>