happy664618843 2022-07-15 16:58 采纳率: 50%
浏览 240
已结题

(有偿问题)计算工人工作时间的问题

有三个时间段是工人的休息时间 如下:
1: 12:00 - 13:00
2: 17:30 - 18:30
3: 20:30 - 08:30

计算工人工作时间要减去休息时间
eg :开始时间(BeginTime):11:00
结束时间(EndTime):19:00
实际工作时间: (19-11)-2(中间休息时间)=4个小时(实际工作时间)

要求:最好C#语言实现: 写一个方法2个参数(开始时间,结束时间) 实时计算出工人实际工作时间(需要考虑跨天计算,超过2天工时按照结束时间 - 开始时间)

  • 写回答

7条回答 默认 最新

  • 码老头 2022-07-16 21:45
    关注

    先看一下运行的结果(支持同天,跨天,跨任意多天等情况,同时还可自定义休息时间段):

    2022-7-13 11:00到2022-7-15 19:00的工时计算结果:

    img

    2022-7-13 11:00到2022-7-17 19:00的工时计算结果:

    img

    以下是C#程序代码实现的逻辑(你可以任意调整BreakTimeRange中的休息时间段):

    namespace ConsoleApp3
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var start = new WorkingDate(new MyDate(2022, 7, 13, 11, 0));
                var end = new WorkingDate(new MyDate(2022, 7, 17, 19, 0));
                var calc = new WorkingHoursCalculator(start, end);
                calc.CalculateWorkingHours();
                Console.WriteLine($"{calc.Start.DateAsString}{calc.End.DateAsString}的工时计算结果如下:");
                Console.WriteLine($"总工时:{calc.TotalWorkingMinutes}分钟(包含休息时间)");
                Console.WriteLine($"实际工时:{calc.ActualWorkingMinutes}分钟(不包含休息时间)");
                Console.WriteLine($"休息时长:{calc.TotalBreakMinutes}分钟");
                Console.WriteLine("=======以下是休息明细=======");
                Console.WriteLine();
                foreach (var item in calc.WorkingTimeItems)
                {
                    Console.WriteLine($"从{item.StartAsString}{item.EndAsString}(工时:{item.ActualWorkingMinutes}分钟,休息{item.TotalBreakMinutes}分钟)");
                    foreach (var breakTimeItem in item.BreakTimeItems)
                    {
                        Console.WriteLine($"{breakTimeItem.BreakTime.Name}时间段休息:{breakTimeItem.BreakMinutes}分钟");
                    }
    
                    Console.WriteLine();
                }
                Console.ReadKey();
            }
        }
    
        public record MyDate(int Year, int Month, int Day, int Hour, int Minute);
    
        public record MyTime(int Hour, int Minute)
        {
            /// <summary>
            /// 转换得到的总的分钟数
            /// </summary>
            public int Minutes => Hour * 60 + Minute;
        }
    
        public record BreakTime(string Name, MyTime Start, MyTime End)
        {
            public int BreakMinutes => End.Minutes - Start.Minutes;
            public int BreakStart => Start.Minutes;
            public int BreakEnd => End.Minutes;
        }
    
        public class BreakTimeRange
        {
            public static List<BreakTime> BreakTimes => new()
            {
                new BreakTime("00:00-08:30",new MyTime(0, 0), new MyTime(8, 30)),
                new BreakTime("12:00-13:00",new MyTime(12, 0), new MyTime(13, 0)),
                new BreakTime("17:00-18:00",new MyTime(17, 30), new MyTime(18, 30)),
                new BreakTime("20:30-24:00",new MyTime(20, 30), new MyTime(24, 0))
            };
        }
    
        public class WorkingDate
        {
            public WorkingDate(MyDate date)
            {
                _myDate = date;
                Year = _myDate.Year;
                Month = _myDate.Month;
                Day = _myDate.Day;
                Hour = _myDate.Hour;
                Minute = _myDate.Minute;
            }
    
            private readonly MyDate _myDate;
            public int Year { get; }
            public int Month { get; }
            public int Day { get; }
            public int Hour { get; }
            public int Minute { get; }
    
            public DateTime Date
            {
                get
                {
                    var hour = _myDate.Hour;
                    var day = _myDate.Day;
                    if (_myDate.Hour == 24)
                    {
                        hour = 0;
                        day += 1;
                    }
    
                    return new DateTime(_myDate.Year, _myDate.Month, day, hour, _myDate.Minute, 0);
                }
            }
    
            public int TotalMinutes => _myDate.Hour * 60 + _myDate.Minute;
            public string DateAsString => $"{_myDate.Year}-{_myDate.Month}-{_myDate.Day} {_myDate.Hour:00}:{_myDate.Minute:00}";
        }
    
        public static class WorkingDateExtension
        {
            public static WorkingDate ConvertToEndOfDay(this WorkingDate workingDate)
            {
                return new WorkingDate(new MyDate(workingDate.Year, workingDate.Month, workingDate.Day, 24,
                    0));
            }
            public static WorkingDate ConvertToStartOfDay(this WorkingDate workingDate)
            {
                return new WorkingDate(new MyDate(workingDate.Year, workingDate.Month, workingDate.Day, 0,
                    0));
            }
    
            public static WorkingDate AddDay(this WorkingDate workingDate)
            {
                return new WorkingDate(new MyDate(workingDate.Year, workingDate.Month, workingDate.Day + 1, workingDate.Hour,
                    workingDate.Minute));
            }
        }
    
        public class BreakTimeItem
        {
            public BreakTime BreakTime { get; set; }
            public int BreakMinutes { get; set; }
        }
    
        public class WorkingTimeItem
        {
            public WorkingTimeItem(WorkingDate start, WorkingDate end)
            {
                Start = start;
                End = end;
                BreakTimeItems = new List<BreakTimeItem>();
            }
            public WorkingDate Start { get; set; }
            public WorkingDate End { get; set; }
            public string DayAsString => Start.Date.ToString("yyyy-MM-dd");
            public string StartAsString => Start.Date.ToString("yyyy-MM-dd HH:mm");
            public string EndAsString => End.Date.ToString("yyyy-MM-dd HH:mm");
    
            /// <summary>
            /// 当天工时(分钟),不包含休息时间
            /// </summary>
            public int ActualWorkingMinutes
            {
                get
                {
                    return End.TotalMinutes - Start.TotalMinutes - BreakTimeItems.Sum(x => x.BreakMinutes);
                }
            }
            /// <summary>
            /// 当天工时(分钟),包含休息时间
            /// </summary>
            public int TotalWorkingMinutes => End.TotalMinutes - Start.TotalMinutes;
    
            /// <summary>
            /// 当天总的休息时长
            /// </summary>
            public int TotalBreakMinutes => BreakTimeItems.Sum(x => x.BreakMinutes);
    
            /// <summary>
            /// 休息明细
            /// </summary>
            public List<BreakTimeItem> BreakTimeItems { get; private set; }
            /// <summary>
            /// 添加休息时间段
            /// </summary>
            /// <param name="item"></param>
            public void AddBreakTimeItem(BreakTimeItem item)
            {
                BreakTimeItems.Add(item);
            }
        }
    
        /// <summary>
        /// 工时计算器
        /// </summary>
        public class WorkingHoursCalculator
        {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="start"></param>
            /// <param name="end"></param>
            public WorkingHoursCalculator(WorkingDate start, WorkingDate end)
            {
                Start = start;
                End = end;
            }
    
            /// <summary>
            /// 开始的天
            /// </summary>
            public int DayOfStart { get; private set; }
    
            /// <summary>
            /// 结束的天
            /// </summary>
            public int DayOfEnd { get; private set; }
    
            /// <summary>
            /// 跨天数
            /// </summary>
            public int CrossDays { get; private set; }
    
            /// <summary>
            /// 两个时期间是否跨天
            /// </summary>
            public bool IsCrossDay => DayOfEnd != DayOfStart;
    
            /// <summary>
            /// 所有天的总工时(包含休息时间)
            /// </summary>
            public double TotalWorkingMinutes => WorkingTimeItems.Sum(x => x.TotalWorkingMinutes);
    
            /// <summary>
            /// 所有天的总实际工时(不包含工作时间)
            /// </summary>
            public double ActualWorkingMinutes => WorkingTimeItems.Sum(x => x.ActualWorkingMinutes);
    
            /// <summary>
            /// 所有天的总休息时长
            /// </summary>
            public double TotalBreakMinutes => WorkingTimeItems.Sum(x => x.TotalBreakMinutes);
    
            public List<WorkingTimeItem> WorkingTimeItems { get; set; }
            public WorkingDate Start { get; set; }
            public WorkingDate End { get; set; }
    
            public void CalculateWorkingHours()
            {
                if (Start.Date > End.Date) throw new ArgumentException("开始时间和结束时间输入错误");
                DayOfStart = Start.Date.Day;
                DayOfEnd = End.Date.Day;
                CrossDays = (End.Date - Start.Date).Days;
                WorkingTimeItems = new List<WorkingTimeItem>();
                if (!IsCrossDay)
                {
                    FindWorkingMinutes(Start, End);
                }
                else
                {
                    // 跨天时
    
                    // 第一天,开始时间到24点
                    FindWorkingMinutes(Start, Start.ConvertToEndOfDay());
                    var days = CrossDays;
                    var current = Start;
                    while (days > 0)
                    {
                        if (days == 1)
                        {
                            FindWorkingMinutes(End.ConvertToStartOfDay(), End);
                            break;
                        }
                        current = current.AddDay();
                        FindWorkingMinutes(current.ConvertToStartOfDay(), current.ConvertToEndOfDay());
                        days--;
                    }
                }
            }
    
            public void FindWorkingMinutes(WorkingDate start, WorkingDate end)
            {
                var wti = new WorkingTimeItem(start, end);
                var aStart = start.TotalMinutes;
                var aEnd = end.TotalMinutes;
                foreach (var breakTime in BreakTimeRange.BreakTimes.Where(breakTime => aStart <= breakTime.BreakEnd && aEnd >= breakTime.BreakStart))
                {
                    if (aStart <= breakTime.BreakStart && aEnd >= breakTime.BreakEnd)
                    {
                        wti.AddBreakTimeItem(new BreakTimeItem
                        {
                            BreakTime = breakTime,
                            BreakMinutes = breakTime.BreakMinutes
                        });
                        continue;
                    }
                    if (aStart <= breakTime.BreakStart && aEnd <= breakTime.BreakEnd)
                    {
                        wti.AddBreakTimeItem(new BreakTimeItem
                        {
                            BreakTime = breakTime,
                            BreakMinutes = aEnd - breakTime.BreakStart
                        });
                        continue;
                    }
                    if (aStart >= breakTime.BreakStart && aEnd >= breakTime.BreakEnd)
                    {
                        wti.AddBreakTimeItem(new BreakTimeItem
                        {
                            BreakTime = breakTime,
                            BreakMinutes = breakTime.BreakEnd - aStart
                        });
                        continue;
                    }
                    if (aStart >= breakTime.BreakStart && aEnd <= breakTime.BreakEnd)
                    {
                        wti.AddBreakTimeItem(new BreakTimeItem
                        {
                            BreakTime = breakTime,
                            BreakMinutes = aEnd - aStart
                        });
                    }
                }
                WorkingTimeItems.Add(wti);
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(6条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月21日
  • 已采纳回答 7月21日
  • 专家修改了标签 7月21日
  • 修改了问题 7月15日
  • 展开全部

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型