【问题标题】:how to add an integer value to a date and calculate the end date in c#如何将整数值添加到日期并在c#中计算结束日期
【发布时间】:2021-08-27 06:25:57
【问题描述】:

我正在构建一个 c# 控制台应用程序。

假设用户输入为

  • 以小时为单位的任务工作量 = 48
  • 每天工作小时数 = 9
  • 开始日期 = 26/02/2021

排除周末和公共假期后,如何显示任务的结束日期。

我已经通过考虑所有可能的验证来实现用户输入。

static void Main(string[] args)
{
    //effort hours
    Console.Write("Enter No of hours: ");
    int hours;
    if (Int32.TryParse(Console.ReadLine(), out hours))
    {
        if (hours <= 0)
        {
            Console.WriteLine("Hours of effort cannot be a negative value or 0");
        }
        else
        {
            Console.WriteLine("The no of hours entered is: " + hours);
        }
    }
    else
    {
        Console.WriteLine("You have entered an incorrect value.");
    }
    Console.ReadLine();

    //working hours per day
    Console.Write("Enter No of working hours per day: ");
    int WorkingHours;
    if (Int32.TryParse(Console.ReadLine(), out WorkingHours))
    {
        if (WorkingHours <= 0 || WorkingHours > 9)
        {
            Console.WriteLine("Maximum working hours per day is 9 hours and no of hours entered cannot be 0 or negative");
        }
        else
        {
            Console.WriteLine("The no of working hours entered is: " + WorkingHours);
        }
    }
    else
    {
        Console.WriteLine("You have entered an incorrect value.");
    }
    Console.ReadLine();

    //Enter start date
    Console.WriteLine("Enter the start date date (e.g. dd/mm/yyyy): ");
    DateTime startDate;
    {
        while (!DateTime.TryParse(Console.ReadLine(), out startDate))
        {
            Console.WriteLine("You have entered an incorrect value.");
            Console.WriteLine("Enter the start date date (e.g. dd/mm/yyyy): ");
        }
        Console.WriteLine("The startdate is: " + startDate);
    }
}

【问题讨论】:

  • 你能定义公共假期吗?不同的国家有不同的公共假期。
  • 您肯定需要一个日历,其中包含域中被视为“周末”、“公共假期”和/或什至“公司假期”的内容(我恰好是一家公司的员工,其中实际上,这是一件事。像我们之间的星期五和星期四的假期这样的“过桥日”是强制性的“不工作”日。)所以,有了这个,你可以计算日期而不考虑日历,然后查看这些非工作日是否属于该范围,然后添加这些天数,然后查看是否有更多非工作日属于添加的范围,冲洗,重复,直到不再是这种情况。跨度>
  • 每个国家都有不同的日期格式。 DateTime.TryParse(Console.ReadLine(), out startDate) NOT 使用 dd/mm/yyyy,它使用用户区域设置中使用的格式。在美国,它将是mm/dd/yyyy。在俄罗斯dd.mm.yyyy
  • 要真正计算工作日,您确实需要一个日历。即使在同一国家的不同部门之间,工作日和工作时间也不同。即使在公司之间。
  • @Fildor 感谢指出无效输入的逻辑错误,我会改正的。

标签: c# datetime console-application


【解决方案1】:

不循环解决这个问题的最简单方法是这样的:

static void Main ( string[] args ) {

    BeginRoutine:
        //effort hours
        Console.Write( "Enter No of hours: " );
        int hours;
        if ( Int32.TryParse( Console.ReadLine(), out hours ) ) {
            if ( hours <= 0 ) {
                Console.WriteLine( "Hours of effort cannot be a negative value or 0" );
            }
            else {
                Console.WriteLine( "The no of hours entered is: " + hours );
            }
        }
        else {
            Console.WriteLine( "You have entered an incorrect value." );
        }
        //Console.ReadLine();

        //working hours per day
        Console.Write( "Enter No of working hours per day: " );
        int WorkingHours;
        if ( Int32.TryParse( Console.ReadLine(), out WorkingHours ) ) {
            if ( WorkingHours <= 0 || WorkingHours > 9 ) {
                Console.WriteLine( "Maximum working hours per day is 9 hours and no of hours entered cannot be 0 or negative" );
            }
            else {
                Console.WriteLine( "The no of working hours entered is: " + WorkingHours );
            }
        }
        else {
            Console.WriteLine( "You have entered an incorrect value." );
        }
        //Console.ReadLine();
    
    GetStartDate:
        //Enter start date
        Console.WriteLine( "Enter the start date date (e.g. dd/mm/yyyy): " );

        DateTime startDate;
        while ( !DateTime.TryParse( Console.ReadLine(), out startDate ) ) {
            Console.WriteLine( "You have entered an incorrect value." );
            Console.WriteLine( "Enter the start date date (e.g. dd/mm/yyyy): " );
        }

        // Make sure the start date isn't a Saturday or Sunday!
        if ( startDate.DayOfWeek == DayOfWeek.Saturday || startDate.DayOfWeek == DayOfWeek.Sunday ) {
            Console.WriteLine( "Cannot start work on {0} because it is a {1}",
                startDate.ToString( "MM/dd/yyyy" ), startDate.DayOfWeek );

            goto GetStartDate;
        }
        Console.WriteLine( "The startdate is: " + startDate );
        
        // Determine number of work days:
        double workDays = hours / WorkingHours;
        Console.WriteLine( "\nTask will take {0} work days", workDays.ToString("0.00") );

        // Determine total weeks and days:
        double totalWeeks = workDays / 5D;
        double totalDays = ( totalWeeks * 7D );

        // Print statistics to Console for user
        Console.WriteLine( "Task will take {0} weeks and {1} total calender days ...", 
            totalWeeks.ToString( "0.00" ), totalDays.ToString( "0.00" ) );

        // Calculate ending date and display it:
        DateTime endDate = startDate.AddDays(totalDays);
        Console.WriteLine( "The ending date will be {0}", endDate.ToString( "MM/dd/yyyy" ) );
        
        // Prompt user to restart:
        Console.WriteLine( "\n\nProgram complete ... press Y to restart or any other key to continue.\n" );
        if ( Console.ReadKey( true ).Key == ConsoleKey.Y ) goto BeginRoutine;
    }

我没有针对所有可能的情况对这个例程进行详尽的测试,这肯定不是做到这一点的“最佳”方式(例如,它不考虑圣诞节等假期,也不针对地区和文化进行本地化)但它似乎以快速高效的方式解决了您的简单问题。奇怪的是,我只是为我的策略游戏原型编写了一些非常有趣的 DateTime 代码,在其中我使用游戏循环来推动 DateTime 前进并创建一个游戏内时间系统。

编辑:请注意,我几乎完好无损地保留了您的原始代码,只是在它下面添加了......解决假期的一种简单方法是创建一个包含假期的日期列表,看看是否有任何落在开始日期和结束日期(可能使用自定义查询),然后为每个日期添加一天。

【讨论】:

  • 很高兴它有帮助。你可以扩展它来做更复杂的事情,比如跳过假期。只需制作一个假期列表,看看哪些是在开始日期和结束日期之间。将每一天添加到 totalDays 中,然后只需调用 DateTime.AddDays 即可获得准确的假期预测(可以基于任何国家或文化的假期)。这种方法的美妙之处在于没有缓慢的循环或混乱的逻辑。我们通过简单的算术来解决这个问题。
  • 是的,当然。我使用简单的 goto 语句来保持代码的简短和简单。但是您可以将其替换为 Main 中的局部函数之类的东西,或者在 Program 类中创建一些静态方法来实现部分例程。然后 Main 将简单地在循环或递归中调用像 Begin() 这样的方法,只要 Console.ReadKey(true).Key 等于 Y 键......非常简单的重组。
  • 我通过包含更多可能的场景修改了代码,现在当工作日超过 10 时我在输出(endDate)中收到错误。但是对于工作日小于或等于的实例,我得到了正确的输出到 10.I 无法弄清楚我的错误..我在stackoverflow.com/questions/68956766/… 中发布了带有修改代码的问题,请您查看并尽可能帮助我。谢谢。
  • 你实际上把它搞砸了,除了错误没有添加任何东西,但我尊重你的努力,并发布了一个使用静态方法而不使用 goto 语句的替代解决方案。不过,我将把一些工作留给你。
【解决方案2】:

如 cmets 中所述,您需要提供世界各地不同的假期列表。此外,定义的“工作日”/“周末”也可能因您开发应用程序的地区而异。例如,一些中东国家/地区在周四/周五有周末。

假设您有固定的周六/周日周末,您可以将 FluentDateTime 提供的 DateTime Extension 修改如下,以包含一系列假期

public static class Extentions
{

    public static DateTime AddBusinessDays(this DateTime current, int days,IEnumerable<DateTime> holidayList)
    {
        var sign = Math.Sign(days);
        var unsignedDays = Math.Abs(days);
        var holidayCollection = new HashSet<DateTime>(holidayList);
        for (var i = 0; i < unsignedDays; i++)
        {
            do
            {
                current = current.AddDays(sign);
            } while (current.DayOfWeek == DayOfWeek.Saturday 
                   || current.DayOfWeek == DayOfWeek.Sunday 
                   || holidayCollection.Contains(current));
        }
        return current;
    }
}

您现在可以使用该方法

startDate.AddBusinessDays(totalHours/perDayHours,holidayList)

如果如前所述,您需要考虑不同的周末,则需要对上面的代码进行适当的更改。

PS:以上代码假设您只对“EndDate”感兴趣,而不是准确的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多