diff --git a/ApiDto/Common/CronUpdateSkip.cs b/ApiDto/Common/CronUpdateSkip.cs
new file mode 100644
index 0000000..822dfc6
--- /dev/null
+++ b/ApiDto/Common/CronUpdateSkip.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mirea.Api.Dto.Common;
+
+///
+/// Represents a date or date range to skip during cron update scheduling.
+///
+public class CronUpdateSkip
+{
+ ///
+ /// Gets or sets the start date of the skip range.
+ ///
+ public DateOnly? Start { get; set; }
+
+ ///
+ /// Gets or sets the end date of the skip range.
+ ///
+ public DateOnly? End { get; set; }
+
+ ///
+ /// Gets or sets a specific date to skip.
+ ///
+ public DateOnly? Date { get; set; }
+}
\ No newline at end of file
diff --git a/ApiDto/Responses/Configuration/CronUpdateScheduleResponse.cs b/ApiDto/Responses/Configuration/CronUpdateScheduleResponse.cs
new file mode 100644
index 0000000..46bab01
--- /dev/null
+++ b/ApiDto/Responses/Configuration/CronUpdateScheduleResponse.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
+namespace Mirea.Api.Dto.Responses.Configuration;
+
+///
+/// Represents the response containing the cron update schedule and the next scheduled task dates.
+///
+public class CronUpdateScheduleResponse
+{
+ ///
+ /// Gets or sets the cron expression representing the update schedule.
+ ///
+ [Required]
+ public required string Cron { get; set; }
+
+ ///
+ /// Gets or sets the list of next scheduled task dates based on the cron expression.
+ ///
+ [Required]
+ public required List NextStart { get; set; }
+}
\ No newline at end of file
diff --git a/Endpoint/Common/MapperDto/CronUpdateSkipConverter.cs b/Endpoint/Common/MapperDto/CronUpdateSkipConverter.cs
new file mode 100644
index 0000000..baa6a0d
--- /dev/null
+++ b/Endpoint/Common/MapperDto/CronUpdateSkipConverter.cs
@@ -0,0 +1,19 @@
+using Mirea.Api.Endpoint.Common.Services;
+using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mirea.Api.Endpoint.Common.MapperDto;
+
+public static class CronUpdateSkipConverter
+{
+ public static List ConvertToDto(this IEnumerable pairPeriod) =>
+ pairPeriod.Select(x => new Dto.Common.CronUpdateSkip()
+ {
+ Start = x.Start,
+ End = x.End,
+ Date = x.Date
+ }).ToList();
+ public static List ConvertFromDto(this IEnumerable pairPeriod) =>
+ pairPeriod.Select(x => x.Get()).ToList();
+}
diff --git a/Endpoint/Controllers/V1/Configuration/ScheduleController.cs b/Endpoint/Controllers/V1/Configuration/ScheduleController.cs
new file mode 100644
index 0000000..6194520
--- /dev/null
+++ b/Endpoint/Controllers/V1/Configuration/ScheduleController.cs
@@ -0,0 +1,132 @@
+using Asp.Versioning;
+using Cronos;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Mirea.Api.DataAccess.Persistence;
+using Mirea.Api.Dto.Common;
+using Mirea.Api.Dto.Responses.Configuration;
+using Mirea.Api.Endpoint.Common.Exceptions;
+using Mirea.Api.Endpoint.Common.MapperDto;
+using Mirea.Api.Endpoint.Common.Services;
+using Mirea.Api.Endpoint.Configuration.Model;
+using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+
+namespace Mirea.Api.Endpoint.Controllers.V1.Configuration;
+
+[ApiVersion("1.0")]
+public class ScheduleController(ILogger logger, IOptionsSnapshot config, UberDbContext dbContext) : ConfigurationBaseController
+{
+ ///
+ /// Retrieves the cron update schedule and calculates the next scheduled tasks based on the provided depth.
+ ///
+ /// The depth of the next tasks to retrieve.
+ /// Cron expression and the list of next scheduled task dates.
+ [HttpGet("CronUpdateSchedule")]
+ public ActionResult CronUpdateSchedule([FromQuery][Range(0, 5)] int depth = 2)
+ {
+ var cronExpression = CronExpression.Parse(config.Value.ScheduleSettings!.CronUpdateSchedule);
+ var nextTasks = config.Value.ScheduleSettings!.CronUpdateSkipDateList.GetNextTask(cronExpression, depth);
+
+ return new CronUpdateScheduleResponse()
+ {
+ Cron = config.Value.ScheduleSettings!.CronUpdateSchedule,
+ NextStart = nextTasks.Select(x => DateTime.SpecifyKind(x.DateTime, DateTimeKind.Local)).ToList()
+ };
+ }
+
+ ///
+ /// Updates the cron update schedule with the provided cron expression.
+ ///
+ /// The cron expression to set as the new schedule.
+ /// Cron expression and the list of next scheduled task dates.
+ /// Thrown if the provided cron expression is invalid.
+ [HttpPost("CronUpdateSchedule")]
+ public ActionResult CronUpdateSchedule([FromBody] string cron)
+ {
+ cron = cron.Trim();
+ if (!CronExpression.TryParse(cron, CronFormat.Standard, out _))
+ throw new ControllerArgumentException("Incorrect cron value.");
+
+ if (config.Value.ScheduleSettings!.CronUpdateSchedule == cron)
+ return Ok(CronUpdateSchedule());
+
+ config.Value.ScheduleSettings!.CronUpdateSchedule = cron;
+ config.Value.SaveSetting();
+
+ return Ok(CronUpdateSchedule());
+ }
+
+ ///
+ /// Retrieves the start term date from the configuration.
+ ///
+ /// Start term date.
+ [HttpGet("StartTerm")]
+ public ActionResult StartTerm() =>
+ config.Value.ScheduleSettings!.StartTerm;
+
+ ///
+ /// Updates the start term date in the configuration.
+ ///
+ /// The new start term date to set.
+ /// If true, forces an update by deleting all existing lessons.
+ /// Success or failure.
+ /// Thrown if the start term date is more than 6 months in the past or future.
+ [HttpPost("StartTerm")]
+ public ActionResult StartTerm([FromBody] DateOnly startTerm, [FromQuery] bool force = false)
+ {
+ var differentByTime = DateTime.Now - startTerm.ToDateTime(new TimeOnly(0, 0, 0));
+ if (differentByTime > TimeSpan.FromDays(190) || differentByTime.Multiply(-1) > TimeSpan.FromDays(190))
+ throw new ControllerArgumentException("The semester can't start more than 6 months from now, and it can't have started more than 6 months ago either.");
+
+ config.Value.ScheduleSettings!.StartTerm = startTerm;
+ config.Value.SaveSetting();
+
+ if (!force)
+ return Ok();
+
+ logger.LogWarning("A force update is being performed at the beginning of the semester (all classes will be deleted).");
+
+ dbContext.Lessons.RemoveRange(dbContext.Lessons.ToList());
+ dbContext.SaveChanges();
+
+ return Ok();
+ }
+
+ ///
+ /// Retrieves the list of cron update skip dates filtered by the current date.
+ ///
+ /// Cron update skip dates.
+ [HttpGet("CronUpdateSkip")]
+ public ActionResult> CronUpdateSkip() =>
+ config.Value.ScheduleSettings!.CronUpdateSkipDateList.Filter(DateTime.Now).ConvertToDto();
+
+ ///
+ /// Updates the list of cron update skip dates in the configuration.
+ ///
+ /// The list of cron update skip dates to set.
+ /// Success or failure.
+ /// Thrown if the provided list of cron update skip dates is invalid.
+ [HttpPost("CronUpdateSkip")]
+ public ActionResult CronUpdateSkip([FromBody] List cronUpdateDate)
+ {
+ List result;
+ try
+ {
+ result = cronUpdateDate.ConvertFromDto();
+ }
+ catch (ArgumentException ex)
+ {
+ throw new ControllerArgumentException(ex.Message);
+ }
+
+ config.Value.ScheduleSettings!.CronUpdateSkipDateList = result.Filter(DateTime.Now);
+ config.Value.SaveSetting();
+
+ return Ok();
+ }
+}
\ No newline at end of file