2016-07-01 3 views
1

Я должен реализовать алгоритм, который получает список DateTime и восстанавливает последнюю DateTime каждую неделю.Как выбрать последнюю датуВремя каждой недели? C#

Пример:

29/06/2016 -> Lastest date of the last week of the month 
27/06/2016 
24/06/2016 -> Lastest date of the before last week of the month 
22/06/2016 
21/06/2016 
15/06/2016 -> Lastest of the third week 
13/06/2016 
... 

Ожидаемый результат

29/06/2016 
24/06/2016 
15/06/2016 

Я не прошу код, который сделал это, но некоторые направления или указание для решения этой проблемы.

+0

Что считаете ли вы «неделю»? С понедельника по воскресенье? С воскресенья по субботу? Что-то другое? –

+0

С понедельника по воскресенье –

+0

Другими словами, вам нужно в конце каждой недели возвращаться? –

ответ

4

Примечание: этот ответ предполагает, что вы заинтересованы в «естественных» неделях, что на самом деле не заботится о годе. Например, 31 декабря 2015 года был четверг, а 1 января 2016 года была пятница - на мой взгляд (и используя алгоритм в этом ответе), которые считались бы на той же неделе ... понедельник до/в оба дня в конце концов.

Простейшим решением для этого, вероятно, является группировка «начало недели», а затем берет последнее значение в каждой группе. Найти начало недели немного неудобно, и лучше всего делать в вспомогательный метод:

var latestPerWeek = dates.GroupBy(StartOfWeek) 
         .Select(g => g.Max()) 
         .ToList(); 

... 

private static DateTime StartOfWeek(DateTime date) 
{ 
    date = date.Date; // Just remove any time parts... 
    // 0=Sunday, 1=Monday... 6=Saturday 
    int sundayToSaturdayDayOfWeek = (int) date.DayOfWeek; 
    // 0=Monday, 1=Tuesday... 6=Sunday 
    int mondayToSundayDayOfWeek = ((sundayToSaturdayDayOfWeek - 1) + 7) % 7; 
    return date.AddDays(-mondayToSundayDayOfWeek); 
} 

Обратите внимание, что .NET «неделя года» обработки заманчиво использовать, но в основном не обрабатывает этот сценарий. В Нода Time 2.0 это будет намного проще, но это пока не доступно ...

+0

Спасибо за ответ и информацию. –

+0

Я немного поиграл с вашим кодом, должен быть в случае '30.12.2015',' 31.12.2015', '01.01.2016' будет один или два действительных результата? Я бы сказал, что «31.12.2015» - последняя из 53-й недели, а «01.01.2016» - последняя из 1-й недели – fubo

+0

@fubo: Нет никаких указаний на то, чего хочет OP - я бы лично предположил, что они хотите каждую неделю составлять ровно 7 дней, поэтому относитесь к 2016-01-01 и 2015-12-31 как к той же неделе. Я добавлю это предположение в ответ, хотя. –

3

Это работает только для дат, которые находятся в том же году

Я хотел бы использовать CultureInfo.InvariantCulture.Calendar.GetWeekOfYear определить номер недели. После этого вы можете GroupBy этот номер и закажите каждую группу по убыванию. Теперь вы просто должны выбрать First() элемент каждую неделю/групп

List<DateTime> dtList = new List<DateTime>(); 
    dtList.Add(new DateTime(2016, 6,29)); 
    dtList.Add(new DateTime(2016,6, 27)); 
    dtList.Add(new DateTime(2016,6 ,24)); 
    dtList.Add(new DateTime(2016,6,22)); 
    dtList.Add(new DateTime(2016,6,21)); 
    dtList.Add(new DateTime(2016,6, 15)); 
    dtList.Add(new DateTime(2016, 6,13)); 

    List<DateTime> dtResult = dtList 
     .GroupBy(x => CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(x, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)) 
     .Select(x => x.OrderByDescending(y => y).First()) 
     .ToList(); 
+0

Это не удастся, если будет задействовано несколько лет, так как они будут сгруппированы по разным годам. К сожалению, недельная обработка .NET не ужасна. –

+0

@JonSkeet, так что вы бы GroupBy Week + Year – fubo

+0

Нет, вы не можете - потому что вы действительно хотите сгруппировать по «недельному году», который не отображается, а границы недель в течение года разделяются на .NET. В принципе, недельная обработка в .NET просто не подходит для работы здесь. Подробнее об этом см. Http://nodatime.org/unstable/userguide/weekyears.html. –

-1

Это работает:

DateTime[] dd = 
{ 
    Convert.ToDateTime("2016/06/29"), 
    Convert.ToDateTime("2016/06/27"), 
    Convert.ToDateTime("2016/06/24"), 
    Convert.ToDateTime("2016/06/22"), 
    Convert.ToDateTime("2016/06/21") 
}; 

Func<DateTime, int> weekProjector = 
    d => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
     d, 
     CalendarWeekRule.FirstFourDayWeek, 
     DayOfWeek.Sunday); 

var LatestByWeek = dd.GroupBy(g => weekProjector(g)).OrderBy(o => o.Max()).Select(s => s.First()); 

LastestByWeek будет содержать то, что вы ищете :)

+0

Нет, это не работает через несколько лет. Ты * только * получаешь неделю. –

+0

Да, я вижу, не заметил этого вначале. –

Смежные вопросы