Вычислить количество рабочих дней между двумя датами?

Использование атрибута required:

Просто добавьте атрибут required к каждому входу, если вы хотите сделать ввод обязательным.

Когда этот атрибут установлен, форма не будет отправлена ​​(и будет отображать сообщение об ошибке), когда ввод пуст (вход также будет считаться недействительным).


Проверьте следующий фрагмент кода и попробуйте отправить форму без заполнения некоторых или всех полей, чтобы увидеть, как работает атрибут required:

<form action="#" name="form" method="POST">
  <div>
    <label>Name</label><br>
    <input type="text" name="name" id="name" placeholder="Name" pattern="[a-zA-Z]*" required>
  </div>
  <div>
    <label>Surname</label><br>
    <input type="text" name="surname" id="surname" placeholder="Surname" pattern="[a-zA-Z]*" required>
  </div>

  <div>
    <label>Email</label><br>
    <input type="email" name="email" id="email" placeholder="Email Address" required>
  </div>

  <div>
    <label>Message</label><br>
    <textarea type="message" name="message" id="email" minlength="1" maxlength="200" placeholder="Message(max 200 characters)" required></textarea>
  </div>
  <input type="submit" name="submit" value="Submit">
</form>


Использование функции JavaScript:

Есть несколько вещей, которые необходимо исправить в JS, а также в HTML :

  1. Измените input type="submit" на button type="button" , чтобы кнопка отправки сначала запустила функцию вместо прямой попытки отправки формы. Также убедитесь, что изменили значение атрибута name и значение атрибута id submit на что-то еще, например submitBtn или submitForm , так что вы можете вручную запустить метод submit() позже в функции.
  2. Добавьте элемент с идентификатором "eresult" , где ваша функция проверки может отправить сообщения об ошибках в.
  3. Добавьте прослушиватель кликов к кнопке отправки, чтобы запустить функцию проверки.
  4. Измените значение атрибута id вашего элемента textarea на message .
  5. Используйте тот же if/else statement , который у вас уже есть, но добавьте return false; к вашему выражению else if и добавьте form.submit() к вашему окончательному else утверждению над return true; .

Н.Б. Мы должны были изменить атрибуты name и id вашей кнопки отправки ранее, чтобы form.submit() ссылался на метод submit(), а не кнопку отправки в функции проверки.


Проверьте и запустите следующий фрагмент кода для практического примера того, что я описал выше:

/* JavaScript */

document.querySelector("button").addEventListener("click", function(){
  var name = document.getElementById('name').value;
  var surname = document.getElementById('surname').value;
  var message = document.getElementById('message').value;
  var email = document.getElementById('email').value;
  if(name=='' || surname=='' || message=='' || email==''){
    document.getElementById("eresult").innerHTML = "All fields required"
    return false;
  }
  else if(name.length<2){
    document.getElementById("eresult").innerHTML = "Name must be atleast 2 charachters"
    return false;
  }

  else{
    form.submit();
    return true;
    
  }
});
<!-- HTML -->

<form action="#" name="form" method="POST">
  <div>
    <label>Name</label><br>
    <input type="text" name="name" id="name" placeholder="Name" pattern="[a-zA-Z]*">
  </div>
  <div>
    <label>Surname</label><br>
    <input type="text" name="surname" id="surname" placeholder="Surname" pattern="[a-zA-Z]*">
  </div>

  <div>
    <label>Email</label><br>
    <input type="email" name="email" id="email" placeholder="Email Address">
  </div>

  <div>
    <label>Message</label><br>
    <textarea type="message" name="message" id="message" minlength="1" maxlength="200" placeholder="Message(max 200 characters)"></textarea>
  </div>
  <button type="button" name="submitBtn">Submit</button>
</form>
<div id="eresult"></div>
[1170 ]

86
задан Partha Sarathi Ghosh 30 January 2016 в 12:14
поделиться

6 ответов

У меня раньше была такая задача, и у меня есть решение. Я бы не стал перечислять все промежуточные дни, когда этого можно избежать, как здесь. Я даже не говорю о создании кучи экземпляров DateTime, как я видел в одном из ответов выше. Это действительно пустая трата вычислительной мощности. Особенно в реальной ситуации, когда вам нужно изучить временные интервалы в несколько месяцев. См. Мой код с комментариями ниже.

    /// <summary>
    /// Calculates number of business days, taking into account:
    ///  - weekends (Saturdays and Sundays)
    ///  - bank holidays in the middle of the week
    /// </summary>
    /// <param name="firstDay">First day in the time interval</param>
    /// <param name="lastDay">Last day in the time interval</param>
    /// <param name="bankHolidays">List of bank holidays excluding weekends</param>
    /// <returns>Number of business days during the 'span'</returns>
    public static int BusinessDaysUntil(this DateTime firstDay, DateTime lastDay, params DateTime[] bankHolidays)
    {
        firstDay = firstDay.Date;
        lastDay = lastDay.Date;
        if (firstDay > lastDay)
            throw new ArgumentException("Incorrect last day " + lastDay);

        TimeSpan span = lastDay - firstDay;
        int businessDays = span.Days + 1;
        int fullWeekCount = businessDays / 7;
        // find out if there are weekends during the time exceedng the full weeks
        if (businessDays > fullWeekCount*7)
        {
            // we are here to find out if there is a 1-day or 2-days weekend
            // in the time interval remaining after subtracting the complete weeks
            int firstDayOfWeek = (int) firstDay.DayOfWeek;
            int lastDayOfWeek = (int) lastDay.DayOfWeek;
            if (lastDayOfWeek < firstDayOfWeek)
                lastDayOfWeek += 7;
            if (firstDayOfWeek <= 6)
            {
                if (lastDayOfWeek >= 7)// Both Saturday and Sunday are in the remaining time interval
                    businessDays -= 2;
                else if (lastDayOfWeek >= 6)// Only Saturday is in the remaining time interval
                    businessDays -= 1;
            }
            else if (firstDayOfWeek <= 7 && lastDayOfWeek >= 7)// Only Sunday is in the remaining time interval
                businessDays -= 1;
        }

        // subtract the weekends during the full weeks in the interval
        businessDays -= fullWeekCount + fullWeekCount;

        // subtract the number of bank holidays during the time interval
        foreach (DateTime bankHoliday in bankHolidays)
        {
            DateTime bh = bankHoliday.Date;
            if (firstDay <= bh && bh <= lastDay)
                --businessDays;
        }

        return businessDays;
    }

Редактировать Slauma, август 2011 г.

Отличный ответ! Однако есть небольшая ошибка. Я вправе редактировать этот ответ, поскольку ответчик отсутствует с 2009 года.

В приведенном выше коде предполагается, что DayOfWeek.Sunday имеет значение 7 , что не соответствует действительности. Фактическое значение равно 0 . Это приводит к неправильному вычислению, если, например, firstDay и lastDay являются одним и тем же воскресеньем. В этом случае метод возвращает 1 , но должно быть 0 .

Самое простое исправление этой ошибки: замените в коде над строками, где firstDayOfWeek и lastDayOfWeek объявлены следующим образом:

int firstDayOfWeek = firstDay.DayOfWeek == DayOfWeek.Sunday 
    ? 7 : (int)firstDay.DayOfWeek;
int lastDayOfWeek = lastDay.DayOfWeek == DayOfWeek.Sunday
    ? 7 : (int)lastDay.DayOfWeek;

Теперь результат:

  • с пятницы по пятницу -> 1
  • с субботы по субботу -> 0
  • с воскресенья по воскресенье -> 0
  • с пятницы по субботу -> 1
  • с пятницы по воскресенье -> 1
  • с пятницы по понедельник -> 2
  • с субботы по понедельник -> 1
  • воскресенье до понедельника -> 1
  • с понедельника по понедельник -> 1
115
ответ дан 24 November 2019 в 07:53
поделиться

Еще один подход для вычисления рабочих дней, не рассмотрения праздников, но принятия во внимание времени суток, возвращая дробную сумму дней:

public static double GetBusinessDays(DateTime startD, DateTime endD)
{
    while (IsWeekend(startD))
        startD = startD.Date.AddDays(1);

    while (IsWeekend(endD))
        endD = endD.Date.AddTicks(-1);

    var bussDays = (endD - startD).TotalDays -
        (2 * ((int)(endD - startD).TotalDays / 7)) -
        (startD.DayOfWeek > endD.DayOfWeek ? 2 : 0);

    return bussDays;
}

public static bool IsWeekend(DateTime d)
{
    return d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday;
}

можно играть с ним здесь: https://rextester.com/ASHRS53997

0
ответ дан 24 November 2019 в 07:53
поделиться
public static int CalculateBusinessDaysInRange(this DateTime startDate, DateTime endDate, params DateTime[] holidayDates)
{
    endDate = endDate.Date;
    if(startDate > endDate)
        throw new ArgumentException("The end date can not be before the start date!", nameof(endDate));
    int accumulator = 0;
    DateTime itterator = startDate.Date;
    do 
    {
        if(itterator.DayOfWeek != DayOfWeek.Saturday && itterator.DayOfWeek != DayOfWeek.Sunday && !holidayDates.Any(hol => hol.Date == itterator))
        { accumulator++; }
    } 
    while((itterator = itterator.AddDays(1)).Date <= endDate);
    return accumulator
}

я только отправляю это, потому что несмотря на все превосходные ответы, которые были даны, ни одна из математики не имела смысл мне. Это - определенно метод KISS, который должен работать и быть довольно удобным в сопровождении. Предоставил, вычисляете ли Вы диапазоны, которые больше, чем 2-3 месяца, это не будет самым эффективным путем. Мы просто определяем, является ли это суббота или в воскресенье или дата является данной праздничной датой. Если это не, мы добавляем рабочий день. Если это затем, все прекрасно.

я уверен, что это могло быть еще более упрощено с LINQ, но этот путь намного легче понять.

0
ответ дан 24 November 2019 в 07:53
поделиться

Вот код для этой цели, со шведскими праздниками, но вы можете настроить, какие праздники считать. Обратите внимание, что я добавил ограничение, которое вы, возможно, захотите удалить, но оно было для веб-системы, и я не хотел, чтобы кто-либо вводил какую-то огромную дату, чтобы заблокировать процесс

  public static int GetWorkdays(DateTime from ,DateTime to)
    {
        int limit = 9999;
        int counter = 0;
        DateTime current = from;
        int result = 0;

        if (from > to)
        {
            DateTime temp = from;
            from = to;
            to = temp;
        }

        if (from >= to)
        {
            return 0;
        }


        while (current <= to && counter < limit)
        {
            if (IsSwedishWorkday(current))
            {
                result++;
            }
            current = current.AddDays(1);
            counter++;

        }
        return result;
    }


    public static bool IsSwedishWorkday(DateTime date)
    {
        return (!IsSwedishHoliday(date) && date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday);
    }

    public static bool IsSwedishHoliday(DateTime date)
    {
        return (
        IsSameDay(GetEpiphanyDay(date.Year), date) ||
        IsSameDay(GetMayDay(date.Year), date) ||
        IsSameDay(GetSwedishNationalDay(date.Year), date) ||
        IsSameDay(GetChristmasDay(date.Year), date) ||
        IsSameDay(GetBoxingDay(date.Year), date) ||
        IsSameDay(GetGoodFriday(date.Year), date) ||
        IsSameDay(GetAscensionDay(date.Year), date) ||
        IsSameDay(GetAllSaintsDay(date.Year), date) ||
        IsSameDay(GetMidsummersDay(date.Year), date) ||
        IsSameDay(GetPentecostDay(date.Year), date) ||
        IsSameDay(GetEasterMonday(date.Year), date) ||
        IsSameDay(GetNewYearsDay(date.Year), date) ||
        IsSameDay(GetEasterDay(date.Year), date)
        );
    }

    // Trettondagen
    public static DateTime GetEpiphanyDay(int year)
    {
        return new DateTime(year, 1, 6);
    }

    // Första maj
    public static DateTime GetMayDay(int year)
    {
        return new DateTime(year,5,1);
    }

    // Juldagen
    public static DateTime GetSwedishNationalDay(int year)
    {
        return new DateTime(year, 6, 6);
    }


    // Juldagen
    public static DateTime GetNewYearsDay(int year)
    {
        return new DateTime(year,1,1);
    }

    // Juldagen
    public static DateTime GetChristmasDay(int year)
    {
        return new DateTime(year,12,25);
    }

    // Annandag jul
    public static DateTime GetBoxingDay(int year)
    {
        return new DateTime(year, 12, 26);
    }


    // Långfredagen
    public static DateTime GetGoodFriday(int year)
    {
        return GetEasterDay(year).AddDays(-3);
    }

    // Kristi himmelsfärdsdag
    public static DateTime GetAscensionDay(int year)
    {
        return GetEasterDay(year).AddDays(5*7+4);
    }

    // Midsommar
    public static DateTime GetAllSaintsDay(int year)
    {
        DateTime result = new DateTime(year,10,31);
        while (result.DayOfWeek != DayOfWeek.Saturday)
        {
            result = result.AddDays(1);
        }
        return result;
    }

    // Midsommar
    public static DateTime GetMidsummersDay(int year)
    {
        DateTime result = new DateTime(year, 6, 20);
        while (result.DayOfWeek != DayOfWeek.Saturday)
        {
            result = result.AddDays(1);
        }
        return result;
    }

    // Pingstdagen
    public static DateTime GetPentecostDay(int year)
    {
        return GetEasterDay(year).AddDays(7 * 7);
    }

    // Annandag påsk
    public static DateTime GetEasterMonday(int year)
    {
        return GetEasterDay(year).AddDays(1);
    }
    public static DateTime GetEasterDay(int y)
    {
        double c;
        double n;
        double k;
        double i;
        double j;
        double l;
        double m;
        double d;
        c = System.Math.Floor(y / 100.0);
        n = y - 19 * System.Math.Floor(y / 19.0);
        k = System.Math.Floor((c - 17) / 25.0);
        i = c - System.Math.Floor(c / 4) - System.Math.Floor((c - k) / 3) + 19 * n + 15;
        i = i - 30 * System.Math.Floor(i / 30);
        i = i - System.Math.Floor(i / 28) * (1 - System.Math.Floor(i / 28) * System.Math.Floor(29 / (i + 1)) * System.Math.Floor((21 - n) / 11));
        j = y + System.Math.Floor(y / 4.0) + i + 2 - c + System.Math.Floor(c / 4);
        j = j - 7 * System.Math.Floor(j / 7);
        l = i - j;
        m = 3 + System.Math.Floor((l + 40) / 44);// month
        d = l + 28 - 31 * System.Math.Floor(m / 4);// day

        double days = ((m == 3) ? d : d + 31);

        DateTime result = new DateTime(y, 3, 1).AddDays(days-1);

        return result;
    }
4
ответ дан 24 November 2019 в 07:53
поделиться

Определите метод расширения для DateTime следующим образом:

public static class DateTimeExtensions
{
    public static bool IsWorkingDay(this DateTime date)
    {
        return date.DayOfWeek != DayOfWeek.Saturday
            && date.DayOfWeek != DayOfWeek.Sunday;
    }
}

Затем используйте в предложении Where для фильтрации более широкого списка дат:

var allDates = GetDates(); // method which returns a list of dates

// filter dates by working day's  
var countOfWorkDays = allDates
     .Where(day => day.IsWorkingDay())
     .Count() ;
22
ответ дан 24 November 2019 в 07:53
поделиться

Хорошо. Думаю, пора опубликовать правильный ответ:

public static double GetBusinessDays(DateTime startD, DateTime endD)
{
    double calcBusinessDays =
        1 + ((endD - startD).TotalDays * 5 -
        (startD.DayOfWeek - endD.DayOfWeek) * 2) / 7;

    if (endD.DayOfWeek == DayOfWeek.Saturday) calcBusinessDays--;
    if (startD.DayOfWeek == DayOfWeek.Sunday) calcBusinessDays--;

    return calcBusinessDays;
}

Первоисточник:

http://alecpojidaev.wordpress.com/2009/10/29/work-days-calculation-with-c/

PS Solutions размещенный выше заставляет меня по какой-то причине.

94
ответ дан 24 November 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: