Level 4

#pragma warning(disable : 4996) //_CRT_SECURE_NO_WARNINGS
#pragma once
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
#include <fstream>
#include "Course7Func.h";
 
using namespace std;
using namespace Course7Func;
 
 
 
namespace Course8Func
{
    struct stDate
    {
        short Year;
        short Month;
        short Day;
    };
    //int GetDifferenceInDays(stDate Date1, stDate Date2);
    short DayOfWeekOrder(short Day, short Month, short Year);
    short DayOfWeekOrder(stDate Date);
 
 
    string NumberToText(int Number)
    {
        if (Number == 0)
        {
            return "";
        }
        if (Number >= 1 && Number <= 19)
        {
            string arr[] = { "",
           "One","Two","Three","Four","Five","Six","Seven",
            "Eight","Nine","Ten","Eleven","Twelve","Thirteen","Fourteen",
            "Fifteen","Sixteen","Seventeen","Eighteen","Nineteen" };
            return arr[Number] + " ";
        }
        if (Number >= 20 && Number <= 99)
        {
            string arr[] = {"","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety" };
 
            return arr[Number / 10] + " " + NumberToText(Number % 10);
        }
        if (Number >= 100 && Number <= 199)
        {
            return "One Hundred " + NumberToText(Number % 100);
        }
        if (Number >= 200 && Number <= 999)
        {
            return NumberToText(Number / 100) + "Hundreds " + NumberToText(Number % 100);
        }
        if (Number >= 1000 && Number <= 1999)
        {
            return "One Thousand " + NumberToText(Number % 1000);
        }
        if (Number >= 2000 && Number <= 999999)
        {
            return NumberToText(Number / 1000) + "Thousands " + NumberToText(Number % 1000);
        }
        if (Number >= 1000000 && Number <= 1999999)
        {
            return "One Million " + NumberToText(Number % 1000000);
        }
        if (Number >= 2000000 && Number <= 999999999)
        {
            return NumberToText(Number / 1000000) + "Millions " + NumberToText(Number % 1000000);
        }
        if (Number >= 1000000000 && Number <= 1999999999)
        {
            return "One Billion " + NumberToText(Number % 1000000000);
        }
        else
        {
            return NumberToText(Number / 1000000000) + "Billions " + NumberToText(Number % 1000000000);
        }
    }
 
    bool IsLeapYear(short Year)
    {
        // leap year if perfectly divisible by 400
        if (Year % 400 == 0) {
            return true;
        }
        // not a leap year if divisible by 100
        // but not divisible by 400
        else if (Year % 100 == 0) {
            return false;
        }
        // leap year if not divisible by 100
        // but divisible by 4
        else if (Year % 4 == 0) {
            return true;
        }
        // all other years are not leap years
        else {
            return false;
        }
    }
    bool isLeapYear(short Year)
    {
        // if year is divisible by 4 AND not divisible by 100
        // OR if year is divisible by 400
        // then it is a leap year
        return (Year % 4 == 0 && Year % 100 != 0) || (Year % 400 == 0);
    }
 
    short ReadYear()
    {
        short Year;
        cout << "\nPlease enter a year to check? ";
        cin >> Year;
        return Year;
    }
    short NumberOfDaysInAYear(short Year)
    {
        return isLeapYear(Year) ? 366 : 365;
    }
    short NumberOfHoursInAYear(short Year)
    {
        return NumberOfDaysInAYear(Year) * 24;
    }
    int NumberOfMinutesInAYear(short Year)
    {
        return NumberOfHoursInAYear(Year) * 60;
    }
    int NumberOfSecondsInAYear(short Year)
    {
        return NumberOfMinutesInAYear(Year) * 60;
    }
 
 
    short NumberOfDaysInAMonth(short Month, short Year)
    {
        if (Month < 1 || Month>12)
            return 0;
        if (Month == 2)
        {
            return isLeapYear(Year) ? 29 : 28;
        }
        short arr31Days[7] = { 1,3,5,7,8,10,12 };
        for (short i = 1; i <= 7; i++)
        {
            if (arr31Days[i - 1] == Month)
                return 31;
        }
        //if you reach here then its 30 days.
        return 30;
    }
    short NumberOfDaysInAMonthOPT(short Month, short Year)
    {
        if (Month < 1 || Month>12)
            return 0;
 
        int NumberOfDays[12] = { 31,28,31,30,31,30,31,31,30,31,30,31};
 
        return (Month == 2) ? (isLeapYear(Year) ? 29 : 28) : NumberOfDays[Month - 1];
    }
    short NumberOfHoursInAMonth(short Month, short Year)
    {
        return NumberOfDaysInAMonth(Month, Year) * 24;
    }
    int NumberOfMinutesInAMonth(short Month, short Year)
    {
        return NumberOfHoursInAMonth(Month, Year) * 60;
    }
    int NumberOfSecondsInAMonth(short Month, short Year)
    {
        return NumberOfMinutesInAMonth(Month, Year) * 60;
    }
    short ReadMonth()
    {
        short Month;
        cout << "\nPlease enter a Month to check? ";
        cin >> Month;
        return Month;
    }
    short ReadDay()
    {
        short Day;
        cout << "\nPlease enter a Day? ";
        cin >> Day;
        return Day;
    }
    short DayOfWeekOrder(short Day, short Month, short Year)
    {
        short a, y, m;
        a = (14 - Month) / 12;
        y = Year - a;
        m = Month + (12 * a) - 2;
        // Gregorian:
        //0:sun, 1:Mon, 2:Tue...etc
        return (Day + y + (y / 4) - (y / 100) + (y / 400) + ((31 * m) / 12)) % 7;
    }
    string DayShortName(short DayOfWeekOrder)
    {
        string arrDayNames[] = {
       "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
        return arrDayNames[DayOfWeekOrder];
    }
    string MonthShortName(short MonthNumber)
    {
        string Months[12] = { "Jan", "Feb", "Mar",
        "Apr", "May", "Jun",
        "Jul", "Aug", "Sep",
        "Oct", "Nov", "Dec"
        };
        return (Months[MonthNumber - 1]);
    }
    void PrintMonthCalendar(short Month, short Year)
    {
        int NumberOfDays;
        // Index of the day from 0 to 6
        int current = DayOfWeekOrder(1, Month, Year);
        NumberOfDays = NumberOfDaysInAMonth(Month, Year);
        // Print the current month name
        printf("\n _______________%s_______________\n\n", MonthShortName(Month).c_str());
        // Print the columns
        printf(" Sun Mon Tue Wed Thu Fri Sat\n");
        // Print appropriate spaces
        int i;
        for (i = 0; i < current; i++)
        {
            printf("    ");
        }
        for (int j = 1; j <= NumberOfDays; j++)
        {
            printf("%4d", j);
            
            if (++i == 7)
            {
                i = 0;
                printf("\n");
            }
        }
        printf("\n _________________________________\n");
    }
    void PrintYearCalendar(int Year)
    {
        printf("\n _________________________________\n\n");
        printf(" Calendar - %d\n", Year);
        printf(" _________________________________\n");
        for (int i = 1; i <= 12; i++)
        {
            PrintMonthCalendar(i, Year);
        }
        return;
    }
    short NumberOfDaysFromTheBeginingOfTheYear(short Day, short Month, short Year)
    {
        short TotalDays = 0;
        for (int i = 1; i <= Month - 1; i++)
        {
            TotalDays += NumberOfDaysInAMonth(i, Year);
        }
        TotalDays += Day;
        return TotalDays;
    }
    
    stDate GetDateFromDayOrderInYear(short DateOrderInYear, short Year)
    {
        stDate Date;
        short RemainingDays = DateOrderInYear;
        short MonthDays = 0;
        Date.Year = Year;
        Date.Month = 1;
 
        while (true)
        {
            MonthDays = NumberOfDaysInAMonth(Date.Month, Year);
            if (RemainingDays > MonthDays)
            {
                RemainingDays -= MonthDays;
                Date.Month++;
            }
            else
            {
                Date.Day = RemainingDays;
                break;
            }
        }
 
        return Date;
    }
    stDate DateAddDays(short Days, stDate Date)
    {
        short RemainingDays = Days + NumberOfDaysFromTheBeginingOfTheYear(Date.Day, Date.Month, Date.Year);
        short MonthDays = 0;
 
        Date.Month = 1;
 
        while (true)
        {
            MonthDays = NumberOfDaysInAMonth(Date.Month, Date.Year);
 
            if (RemainingDays > MonthDays)
            {
                RemainingDays -= MonthDays;
                Date.Month++;
 
                if (Date.Month > 12)
                {
                    Date.Month = 1;
                    Date.Year++;
                }
            }
            else
            {
                Date.Day = RemainingDays;
                break;
            }
        }
        return Date;
    }
    stDate ReadFullDate()
    {
        stDate Date;
        Date.Day = ReadDay();
        Date.Month = ReadMonth();
        Date.Year = ReadYear();
        return Date;
    }
    short ReadDaysToAdd()
    {
        short Days;
        cout << "\nHow many days to add? ";
        cin >> Days;
        return Days;
    }
 
 
    bool IsDate1BeforeDate2(stDate Date1, stDate Date2)
    {
        return
            (Date1.Year < Date2.Year) ? // �� ����� ����� ������� ����� ���� �� ����� ����� ������� �������
            true : (
 
                (Date1.Year == Date2.Year) ? // �� ��� ����ɿ 
 
            (Date1.Month < Date2.Month ?  // �� ��� ����� ���� �� ��� �������
 
                true : (Date1.Month == Date2.Month ? // �� ��� ����� ��� ��� ������
 
                Date1.Day < Date2.Day : false) // �� ���� ������� ����� ���� �� ���� ������� �������
                
                ) : false);
    }
    bool IsDate1EqualDate2(stDate Date1, stDate Date2)
    {
        return (Date1.Year == Date2.Year) ? (
                
                (Date1.Month == Date2.Month) ? (
                   
                (Date1.Day == Date2.Day) ? true : false
                    
                    ) : false
                
                ) : false;
    }
 
    bool IsLastDayInMonth(stDate Date)
    {
        return (
            Date.Day == NumberOfDaysInAMonth(Date.Month, Date.Year)
            );
    }
 
    bool IsLastMonthInYear(short Month)
    {
        return (Month == 12);
    }
 
    stDate IncreaseDateByOneDay(stDate Date)
    {
        if (IsLastDayInMonth(Date))
        {
            if (IsLastMonthInYear(Date.Month))
            {
                Date.Month = 1;
                Date.Day = 1;
                Date.Year++;
            }
            else
            {
                Date.Day = 1;
                Date.Month++;
            }
        }
        else
        {
            Date.Day++;
        }
 
        return Date;
    }
 
    int GetDifferenceInDays(stDate Date1, stDate Date2, bool IncludeEndDay = false)
    {
        int Days = 0;
 
        while (IsDate1BeforeDate2(Date1, Date2))
        {
            Days++;
            Date1 = IncreaseDateByOneDay(Date1);
        }
 
        return IncludeEndDay ? ++Days : Days;
    }
 
    stDate GetSystemDate()
    {
        stDate Date;
 
        time_t t = time(0);
        tm* now = localtime(&t);
 
        Date.Year = now->tm_year + 1900;
        Date.Month = now->tm_mon + 1;
        Date.Day = now->tm_mday;
 
        return Date;
    }
 
    void SwapDates(stDate& Date1, stDate& Date2)
    {
        stDate TempDate;
 
        TempDate.Year = Date1.Year;
        TempDate.Month = Date1.Month;
        TempDate.Day = Date1.Day;
 
        Date1.Year = Date2.Year;
        Date1.Month = Date2.Month;
        Date1.Day = Date2.Day;
 
        Date2.Year = TempDate.Year;
        Date2.Month = TempDate.Month;
        Date2.Day = TempDate.Day;
    }
 
    //���� �� ������� ������ ��� �� ����� ���� �������� ������
    int GetDifferenceInDaysSupport(stDate Date1, stDate Date2, bool IncludeEndDay = false)
    {
        int Days = 0;
        short SawpFlagValue = 1;
        if (!IsDate1BeforeDate2(Date1, Date2))
        {
            //Swap Dates
            SwapDates(Date1, Date2);
            SawpFlagValue = -1;
        }
        while (IsDate1BeforeDate2(Date1, Date2))
        {
            Days++;
            Date1 = IncreaseDateByOneDay(Date1);
        }
        return IncludeEndDay ? ++Days * SawpFlagValue : Days * SawpFlagValue;
    }
 
 
    //p20 - 32
    stDate IncreaseDateByXDays(short Days, stDate Date)
    {
        for (short i = 1; i <= Days; i++)
        {
            Date = IncreaseDateByOneDay(Date);
        }
        return Date;
    }
 
    stDate IncreaseDateByOneWeek(stDate Date)
    {
        for (int i = 1; i <= 7; i++)
        {
            Date = IncreaseDateByOneDay(Date);
        }
        return Date;
    }
    stDate IncreaseDateByXWeeks(short Weeks, stDate Date)
    {
        for (short i = 1; i <= Weeks; i++)
        {
            Date = IncreaseDateByOneWeek(Date);
        }
        return Date;
    }
 
    stDate IncreaseDateByOneMonth(stDate Date)
    {
        if (Date.Month == 12)
        {
            Date.Month = 1;
            Date.Year++;
        }
        else
        {
            Date.Month++;
        }
        //last check day in date should not exceed max days in the current month
        // example if date is 31/1/2022 increasing one month should not be 31 / 2 / 2022, it should
        // be 28/2/2022
        short NumberOfDaysInCurrentMonth = 
            NumberOfDaysInAMonth(Date.Month, Date.Year);
 
        if (Date.Day > NumberOfDaysInCurrentMonth)
        {
            Date.Day = NumberOfDaysInCurrentMonth;
        }
 
        return Date;
    }
    stDate IncreaseDateByXMonths(short Months, stDate Date)
    {
        for (short i = 1; i <= Months; i++)
        {
            Date = IncreaseDateByOneMonth(Date);
        }
        return Date;
    }
 
    stDate IncreaseDateByOneYear(stDate Date)
    {
        Date.Year++;
        return Date;
    }
    stDate IncreaseDateByXYears(short Years, stDate Date)
    {
        for (short i = 1; i <= Years; i++)
        {
            Date = IncreaseDateByOneYear(Date);
        }
        return Date;
    }
    stDate IncreaseDateByXYearsFaster(short Years, stDate Date)
    {
        Date.Year += Years;
        return Date;
    }
 
    stDate IncreaseDateByOneDecade(stDate Date)
    {
        //Period of 10 years
        Date.Year += 10;
        return Date;
    }
    stDate IncreaseDateByXDecades(short Decade, stDate Date)
    {
        for (short i = 1; i <= Decade * 10; i++)
        {
            Date = IncreaseDateByOneYear(Date);
        }
        return Date;
    }
    stDate IncreaseDateByXDecadesFaster(short Decade, stDate Date)
    {
        Date.Year += Decade * 10;
        return Date;
    }
 
    stDate IncreaseDateByOneCentury(stDate Date)
    {
        //Period of 100 years
        Date.Year += 100;
        return Date;
    }
 
    stDate IncreaseDateByOneMillennium(stDate Date)
    {
        //Period of 1000 years
        Date.Year += 1000;
        return Date;
    }
 
 
 
    //#33 to 46
    stDate DecreaseDateByOneDay(stDate Date)
    {
        if (Date.Day == 1)
        {
            if (Date.Month == 1)
            {
                Date.Month = 12;
                Date.Day = 31;
                Date.Year--;
            }
            else
            {
                Date.Month--;
                Date.Day = NumberOfDaysInAMonth(Date.Month, Date.Year);
            }
        }
        else
        {
            Date.Day--;
        }
        return Date;
    }
    stDate DecreaseDateByXDays(short Days, stDate Date)
    {
        for (short i = 1; i <= Days; i++)
        {
            Date = DecreaseDateByOneDay(Date);
        }
        return Date;
    }
 
    stDate DecreaseDateByOneWeek(stDate Date)
    {
        for (int i = 1; i <= 7; i++)
        {
            Date = DecreaseDateByOneDay(Date);
        }
        return Date;
    }
    stDate DecreaseDateByXWeeks(short Weeks, stDate Date)
    {
        for (short i = 1; i <= Weeks; i++)
        {
            Date = DecreaseDateByOneWeek(Date);
        }
        return Date;
    }
 
    stDate DecreaseDateByOneMonth(stDate Date)
    {
        if (Date.Month == 1)
        {
            Date.Month = 12;
            Date.Year--;
        }
        else
            Date.Month--;
        //last check day in date should not exceed max days in the current month
            // example if date is 31/3/2022 decreasing one month should not be 31 / 2 / 2022, it should
            // be 28/2/2022
 
        short NumberOfDaysInCurrentMonth =
            NumberOfDaysInAMonth(Date.Month, Date.Year);
 
        if (Date.Day > NumberOfDaysInCurrentMonth)
        {
            Date.Day = NumberOfDaysInCurrentMonth;
        }
        return Date;
    }
    stDate DecreaseDateByXMonths(short Months, stDate Date)
    {
        for (short i = 1; i <= Months; i++)
        {
            Date = DecreaseDateByOneMonth(Date);
        }
        return Date;
    }
 
    stDate DecreaseDateByOneYear(stDate Date)
    {
        Date.Year--;
        return Date;
    }
    stDate DecreaseDateByXYears(short Years, stDate Date)
    {
        for (short i = 1; i <= Years; i++)
        {
            Date = DecreaseDateByOneYear(Date);
        }
        return Date;
    }
    stDate DecreaseDateByXYearsFaster(short Years, stDate Date)
    {
        Date.Year -= Years;
        return Date;
    }
 
    stDate DecreaseDateByOneDecade(stDate Date)
    {
        //Period of 10 years
        Date.Year -= 10;
        return Date;
    }
    stDate DecreaseDateByXDecades(short Decade, stDate Date)
    {
        for (short i = 1; i <= Decade * 10; i++)
        {
            Date = DecreaseDateByOneYear(Date);
        }
        return Date;
    }
    stDate DecreaseDateByXDecadesFaster(short Decade, stDate Date)
    {
        Date.Year -= Decade * 10;
        return Date;
    }
 
    stDate DecreaseDateByOneCentury(stDate Date)
    {
        //Period of 100 years
        Date.Year -= 100;
        return Date;
    }
 
    stDate DecreaseDateByOneMillennium(stDate Date)
    {
        //Period of 1000 years
        Date.Year -= 1000;
        return Date;
    }
 
 
    
    //#47 to 53
    
    short DayOfWeekOrder(stDate Date)
    {
        return DayOfWeekOrder(Date.Day, Date.Month, Date.Year);
    }
 
    short IsEndOfWeek(stDate Date)//����� ������� ��� ����� ����� ��� �����
    {
        return DayOfWeekOrder(Date) == 6;// ����� ������ ����
    }
 
    bool IsWeekEnd(stDate Date)
    {
        //Weekends are Fri and Sat
        short DayIndex = DayOfWeekOrder(Date);
        return (DayIndex == 5 || DayIndex == 6);
    }
 
    bool IsBusinessDay(stDate Date)
    {
        //Business days are Sun,Mon,Tue,Wed and Thur
        /* 
        short DayIndex = DayOfWeekOrder(Date);
        return (DayIndex >= 5 && DayIndex <= 4);
        */
        //shorter method is to invert the IsWeekEnd: this will save updating code.
        return !IsWeekEnd(Date);
    }
 
    short DaysUntilTheEndOfWeek(stDate Date)
    {
        return 6 - DayOfWeekOrder(Date);
    }
    short DaysUntilTheEndOfMonth(stDate Date1)
    {
        stDate EndOfMontDate;
 
        EndOfMontDate.Day = NumberOfDaysInAMonth(Date1.Month, Date1.Year);
        EndOfMontDate.Month = Date1.Month;
        EndOfMontDate.Year = Date1.Year;
 
        return GetDifferenceInDays(Date1, EndOfMontDate, true);
    }
    short DaysUntilTheEndOfYear(stDate Date1)
    {
        stDate EndOfYearDate;
 
        EndOfYearDate.Day = 31;
        EndOfYearDate.Month = 12;
        EndOfYearDate.Year = Date1.Year;
 
        return GetDifferenceInDays(Date1, EndOfYearDate, true);
    }
 
 
 
    //p54
    // ������ ������ �������� ��� ������ ��� ���� �������
    short CalculateVacationDays(stDate DateFrom, stDate DateTo)
    {
        short DaysCount = 0;
 
        while (IsDate1BeforeDate2(DateFrom, DateTo))
        {
            if (IsBusinessDay(DateFrom))
                DaysCount++;
 
            DateFrom = IncreaseDateByOneDay(DateFrom);
        }
 
        return DaysCount;
    }
 
 
 
    //p55
    // ����� ����� ������ ��� �������
    // �� ������� ���� ����� �� ������ �� ���� �������
    // ����� ���� ������� ������ ���� ���� ��� ���� ������� ������� �� ��� ���� ����� �������� ����� �������
    stDate CalculateVacationReturnDate(stDate DateFrom, short VacationDays)
    {
 
        short WeekEndCounter = 0;
 
        //in case the date is weekend keep adding one day util you reach business day
        //we get rid of all weekends before the first business day
        // �������
        while (IsWeekEnd(DateFrom))
        {
            DateFrom = IncreaseDateByOneDay(DateFrom);
        }
 
        //here we increase the vacation dates to add all weekends to it.
 
        for (short i = 1; i <= VacationDays + WeekEndCounter; i++)
        {
 
            if (IsWeekEnd(DateFrom))
                WeekEndCounter++;
 
            DateFrom = IncreaseDateByOneDay(DateFrom);
        }
 
        //in case the return date is week end keep adding one day util you reach business day
        // �������
        while (IsWeekEnd(DateFrom))
        {
            DateFrom = IncreaseDateByOneDay(DateFrom);
        }
 
        return DateFrom;
    }
    short ReadVacationDays()
    {
        short Days;
        cout << "\nPlease enter vacation days? ";
        cin >> Days;
        return Days;
    }
 
 
 
 
    //p56
    bool IsDate1AfterDate2(stDate Date1, stDate Date2)
    {
        return (
 
            !IsDate1BeforeDate2(Date1, Date2) &&
            !IsDate1EqualDate2(Date1, Date2)
 
            );
    }
 
 
    //p57
    enum enDateCompare { Before = -1, Equal = 0, After = 1 };
 
    enDateCompare CompareDates(stDate Date1, stDate Date2)
    {
        if (IsDate1BeforeDate2(Date1, Date2))
            return enDateCompare::Before;
 
        if (IsDate1EqualDate2(Date1, Date2))
            return enDateCompare::Equal;
 
        /* if (IsDate1AfterDate2(Date1,Date2))
        return enDateCompare::After;*/
        //this is faster
        return enDateCompare::After;
    }
 
 
 
 
    //p58
    struct stPeriod
    {
        stDate StartDate;
        stDate EndDate;
    };
 
 
    stPeriod ReadPeriod()
    {
        stPeriod Period;
 
        cout << "\nEnter Start Date:\n";
        Period.StartDate = ReadFullDate();
 
        cout << "\nEnter End Date:\n";
        Period.EndDate = ReadFullDate();
 
        return Period;
    }
    bool IsOverlapPeriods(stPeriod Period1, stPeriod Period2)
    {
        if (
            CompareDates(Period2.EndDate, Period1.StartDate) ==
            enDateCompare::Before
            ||
            CompareDates(Period2.StartDate, Period1.EndDate) ==
            enDateCompare::After
            )
            return false;
        else
            return true;
    }
 
 
 
 
    //p59
    int PeriodLengthInDays(stPeriod Period, bool IncludeEndDate = false)
    {
        return GetDifferenceInDays(Period.StartDate, Period.EndDate,
            IncludeEndDate);
    }
 
 
 
    //p60
    bool isDateInPeriod(stDate Date, stPeriod Period)
    {
        return !(
            
            CompareDates(Date, Period.StartDate) ==
            enDateCompare::Before
            ||
            CompareDates(Date, Period.EndDate) ==
            enDateCompare::After
            
            );
    }
 
 
 
 
    //p61
    int CountOverlapDays(stPeriod Period1, stPeriod Period2)
    {
        int Period1Length = PeriodLengthInDays(Period1, true);
        int Period2Length = PeriodLengthInDays(Period2, true);
        int OverlapDays = 0;
        // ��� ����� ��������� ���� ����� �� ��� ������� ��� ��
        if (!IsOverlapPeriods(Period1, Period2))
            return 0;
        // ���� ���� ��� ��� ����� ������ ������� ������� ������ 
        // ���� ���� ���� �� ����� ���� ��� �� ����
        if (Period1Length < Period2Length)
        {
            while (IsDate1BeforeDate2(Period1.StartDate,
                Period1.EndDate))
            {
                if (isDateInPeriod(Period1.StartDate, Period2))
                    OverlapDays++;
                Period1.StartDate =
                    IncreaseDateByOneDay(Period1.StartDate);
            }
        }
        else
        {
            while (IsDate1BeforeDate2(Period2.StartDate,
                Period2.EndDate))
            {
                if (isDateInPeriod(Period2.StartDate, Period1))
                    OverlapDays++;
                Period2.StartDate =
                    IncreaseDateByOneDay(Period2.StartDate);
            }
        }
        return OverlapDays;
    }
 
 
    //p62
    bool IsValidDate(stDate Date)
    {
        if (Date.Day < 1 || Date.Day>31)
            return false;
        if (Date.Month < 1 || Date.Month>12)
            return false;
        if (Date.Month == 2)
        {
            if (isLeapYear(Date.Year))
            {
                if (Date.Day > 29)
                    return false;
            }
            else
            {
                if (Date.Day > 28)
                    return false;
            }
        }
 
        short DaysInMonth = NumberOfDaysInAMonth(Date.Month, Date.Year);
        if (Date.Day > DaysInMonth)
            return false;
 
        return true;
    }
 
 
    //p63 - 64
    string DateToString(stDate Date)
    {
        return to_string(Date.Day) + "/" + to_string(Date.Month) +
            "/" + to_string(Date.Year);
    }
    stDate StringToDate(string DateString)
    {
        stDate Date;
        vector <string> vDate;
 
        vDate = SplitString(DateString, "/");
 
        Date.Day = stoi(vDate[0]);
        Date.Month = stoi(vDate[1]);
        Date.Year = stoi(vDate[2]);
 
        return Date;
    }
 
 
    string ReadStringDate(string Message)
    {
        string DateString;
        cout << Message;
        getline(cin >> ws, DateString);
        return DateString;
    }
 
 
    //p65
    string ReplaceWordInString(string S1, 
        string StringToReplace, string sRepalceTo)
    {
        short pos = S1.find(StringToReplace);
        while (pos != std::string::npos)
        {
            S1 = S1.replace(pos, StringToReplace.length(),
                sRepalceTo);
            pos = S1.find(StringToReplace);//find next
        }
        return S1;
    }
 
 
    string FormateDate(stDate Date,
        string DateFormat = "dd/mm/yyyy")
    {
        string FormattedDateString = "";
 
        FormattedDateString = ReplaceWordInString(
            DateFormat,
            "dd",
            to_string(Date.Day));
 
        FormattedDateString = ReplaceWordInString(
            FormattedDateString,
            "mm",
            to_string(Date.Month)
        );
 
        FormattedDateString = ReplaceWordInString(
            FormattedDateString,
            "yyyy",
            to_string(Date.Year)
        );
 
        return FormattedDateString;
    }
 
 
}