public async Task <List <EffortUsedByRoleByDate> > CalculateACByRoleAndSave(string projectGid, string taskGid, DateTime startDate, DateTime endDate, List <TimeEntry> timeEntries = null)
        {
            if (timeEntries == null)
            {
                // 如果没有传的话,就取一遍
                var timeEntriesQ1 = await WhereAsync(a => a.ProjectId == projectGid && a.Date >= startDate && a.Date <= endDate && a.IsDeleted == false);

                if (!string.IsNullOrEmpty(taskGid))
                {
                    timeEntriesQ1 = timeEntriesQ1.Where(a => a.TaskId == taskGid);
                }

                timeEntries = timeEntriesQ1.ToList();
            }


            var timeEntriesQ = timeEntries.Where(a => a.ProjectId == projectGid);

            if (!string.IsNullOrEmpty(taskGid))
            {
                timeEntriesQ = timeEntriesQ.Where(a => a.TaskId == taskGid);
            }

            if (timeEntriesQ.Count() == 0)
            {
                return(new List <EffortUsedByRoleByDate>());
            }

            var rolesByMonth       = new Dictionary <string, List <EmployeeTitle> >();
            var timeEntriesByMonth = new Dictionary <string, List <TimeEntryWithRoleViewModel> >();
            var sdate = startDate.AddDays(-startDate.Day + 1);
            var edate = endDate.AddDays(-endDate.Day + 1);

            for (var month = sdate; month <= edate; month = month.AddMonths(1))
            {
                var roleByMonth = await _employeeTitleService.ListByMonth(month.Year, month.Month);

                rolesByMonth.Add(month.ToString("yyyyMM"), roleByMonth);

                var timeEntriesByTaskByMonth = from timeEntry in timeEntriesQ.Where(a => a.Date >= month && a.Date < month.AddMonths(1))
                                               join role in roleByMonth on timeEntry.UserId equals role.EmployeeGid
                                               select new TimeEntryWithRoleViewModel()
                {
                    Gid         = timeEntry.Gid,
                    Description = timeEntry.Description,
                    Date        = timeEntry.Date,
                    ProjectId   = projectGid,
                    TaskId      = taskGid,
                    RoleId      = role.RoleId,
                    IsBillable  = timeEntry.IsBillable,
                    TotalHours  = timeEntry.TotalHours,
                    UserId      = timeEntry.UserId
                };

                if (timeEntriesByTaskByMonth.Count() == 0)
                {
                    continue;
                }

                timeEntriesByMonth.Add(month.ToString("yyyyMM"), timeEntriesByTaskByMonth.ToList());
            }

            var effortUsed = new List <EffortUsedByRoleByDate>();

            for (var date = startDate; date <= endDate; date = date.AddDays(1))
            {
                var month = date.AddDays(-date.Day + 1);

                var timeEntriesByRoleByMonth = timeEntriesByMonth.GetValueOrDefault(month.ToString("yyyyMM"));
                if (timeEntriesByRoleByMonth == null || timeEntriesByRoleByMonth.Count() == 0)
                {
                    continue;
                }
                effortUsed.AddRange(await CalculateACByDateByRoleAndSave(projectGid, taskGid, date, timeEntriesByRoleByMonth));
            }

            return(effortUsed);
        }