Загрузка данных


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace CalendarApp
{
    class Program
    {
        static void Main()
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            var calendar = new CalendarService();

            while (true)
            {
                Console.Clear();
                Console.WriteLine("=== КАЛЕНДАРЬ ===");
                Console.WriteLine("1. Показать месяц");
                Console.WriteLine("2. Показать текущий месяц");
                Console.WriteLine("3. Поиск по дню недели");
                Console.WriteLine("4. Поиск по дню месяца");
                Console.WriteLine("5. Поиск по конкретной дате");
                Console.WriteLine("6. Поиск по диапазону дат");
                Console.WriteLine("7. Найти ближайший день недели");
                Console.WriteLine("0. Выход");
                Console.Write("\nВыберите пункт: ");

                var choice = Console.ReadLine();
                Console.WriteLine();

                try
                {
                    switch (choice)
                    {
                        case "1":
                            ShowMonthMenu(calendar);
                            break;
                        case "2":
                            calendar.PrintMonth(DateTime.Today.Year, DateTime.Today.Month);
                            break;
                        case "3":
                            SearchByDayOfWeek(calendar);
                            break;
                        case "4":
                            SearchByDayOfMonth(calendar);
                            break;
                        case "5":
                            SearchByExactDate(calendar);
                            break;
                        case "6":
                            SearchByDateRange(calendar);
                            break;
                        case "7":
                            FindNearestDayOfWeek(calendar);
                            break;
                        case "0":
                            return;
                        default:
                            Console.WriteLine("Неверный выбор.");
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка: {ex.Message}");
                }

                Console.WriteLine("\nНажмите любую клавишу...");
                Console.ReadKey();
            }
        }

        static void ShowMonthMenu(CalendarService calendar)
        {
            Console.Write("Введите год: ");
            int year = int.Parse(Console.ReadLine());
            Console.Write("Введите месяц (1-12): ");
            int month = int.Parse(Console.ReadLine());
            calendar.PrintMonth(year, month);
        }

        static void SearchByDayOfWeek(CalendarService calendar)
        {
            Console.WriteLine("Дни недели: Понедельник, Вторник, Среда, Четверг, Пятница, Суббота, Воскресенье");
            Console.Write("Введите день недели: ");
            var input = Console.ReadLine();

            if (!Enum.TryParse<DayOfWeek>(input, true, out var dow))
                throw new Exception("Неверный день недели");

            Console.Write("Начало поиска (дд.мм.гггг): ");
            var start = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);
            Console.Write("Конец поиска (дд.мм.гггг): ");
            var end = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);

            var dates = calendar.FindByDayOfWeek(start, end, dow);

            Console.WriteLine($"\nНайдено {dates.Count} совпадений:");
            foreach (var d in dates)
                Console.WriteLine($"  {d:dd.MM.yyyy} — {d.DayOfWeek}");
        }

        static void SearchByDayOfMonth(CalendarService calendar)
        {
            Console.Write("Введите день месяца (1-31): ");
            int day = int.Parse(Console.ReadLine());
            Console.Write("Год поиска: ");
            int year = int.Parse(Console.ReadLine());

            var dates = calendar.FindByDayOfMonth(year, day);

            Console.WriteLine($"\nДни с числом {day} в {year}:");
            foreach (var d in dates)
                Console.WriteLine($"  {d:dd.MM.yyyy} ({d.DayOfWeek})");
        }

        static void SearchByExactDate(CalendarService calendar)
        {
            Console.Write("Введите дату (дд.мм.гггг): ");
            var date = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);

            calendar.PrintDateInfo(date);
        }

        static void SearchByDateRange(CalendarService calendar)
        {
            Console.Write("Начало (дд.мм.гггг): ");
            var start = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);
            Console.Write("Конец (дд.мм.гггг): ");
            var end = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);

            var dates = calendar.GetRange(start, end);
            Console.WriteLine($"\nВсего дней: {dates.Count}");

            foreach (var d in dates)
                Console.WriteLine($"  {d:dd.MM.yyyy} — {d.DayOfWeek}");
        }

        static void FindNearestDayOfWeek(CalendarService calendar)
        {
            Console.Write("Введите день недели: ");
            var input = Console.ReadLine();
            if (!Enum.TryParse<DayOfWeek>(input, true, out var dow))
                throw new Exception("Неверный день недели");

            Console.Write("От какой даты искать (дд.мм.гггг): ");
            var from = DateTime.ParseExact(Console.ReadLine(), "dd.MM.yyyy", CultureInfo.InvariantCulture);

            var nearest = calendar.FindNearestDayOfWeek(from, dow);
            Console.WriteLine($"\nБлижайший {dow}: {nearest:dd.MM.yyyy}");
        }
    }

    public class CalendarService
    {
        public static readonly string[] MonthNames =
        {
            "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь",
            "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"
        };

        /// <summary>Печатает календарь месяца.</summary>
        public void PrintMonth(int year, int month)
        {
            if (month < 1 || month > 12)
                throw new ArgumentOutOfRangeException(nameof(month));

            Console.WriteLine($"\n     {MonthNames[month - 1]} {year}");
            Console.WriteLine("Пн Вт Ср Чт Пт Сб Вс");

            var first = new DateTime(year, month, 1);
            int daysInMonth = DateTime.DaysInMonth(year, month);

            // Смещение: понедельник = 0, воскресенье = 6
            int offset = ((int)first.DayOfWeek + 6) % 7;

            for (int i = 0; i < offset; i++)
                Console.Write("   ");

            for (int day = 1; day <= daysInMonth; day++)
            {
                Console.Write($"{day,2} ");
                if ((offset + day) % 7 == 0)
                    Console.WriteLine();
            }
            Console.WriteLine();
        }

        /// <summary>Все даты с указанным днём недели в диапазоне.</summary>
        public List<DateTime> FindByDayOfWeek(DateTime start, DateTime end, DayOfWeek dayOfWeek)
        {
            if (start > end) (start, end) = (end, start);

            var result = new List<DateTime>();
            int diff = ((int)dayOfWeek - (int)start.DayOfWeek + 7) % 7;
            var current = start.AddDays(diff);

            while (current <= end)
            {
                result.Add(current);
                current = current.AddDays(7);
            }
            return result;
        }

        /// <summary>Все даты с заданным числом месяца в году.</summary>
        public List<DateTime> FindByDayOfMonth(int year, int day)
        {
            var result = new List<DateTime>();
            for (int m = 1; m <= 12; m++)
            {
                if (day <= DateTime.DaysInMonth(year, m))
                    result.Add(new DateTime(year, m, day));
            }
            return result;
        }

        /// <summary>Подробная информация о дате.</summary>
        public void PrintDateInfo(DateTime date)
        {
            var culture = new CultureInfo("ru-RU");
            Console.WriteLine($"\nДата: {date:dd.MM.yyyy}");
            Console.WriteLine($"День недели: {date.DayOfWeek}");
            Console.WriteLine($"Месяц: {MonthNames[date.Month - 1]}");
            Console.WriteLine($"Год: {date.Year}");
            Console.WriteLine($"День года: {date.DayOfYear}");
            Console.WriteLine($"Номер недели: {ISOWeek.GetWeekOfYear(date)}");
            Console.WriteLine($"Високосный год: {(DateTime.IsLeapYear(date.Year) ? "да" : "нет")}");
        }

        /// <summary>Все дни диапазона.</summary>
        public List<DateTime> GetRange(DateTime start, DateTime end)
        {
            if (start > end) (start, end) = (end, start);

            var list = new List<DateTime>();
            for (var d = start.Date; d <= end.Date; d = d.AddDays(1))
                list.Add(d);
            return list;
        }

        /// <summary>Ближайший день недели, начиная с указанной даты (включительно).</summary>
        public DateTime FindNearestDayOfWeek(DateTime from, DayOfWeek dayOfWeek)
        {
            int diff = ((int)dayOfWeek - (int)from.DayOfWeek + 7) % 7;
            return from.AddDays(diff);
        }
    }
}