как проверить, существуют ли даты в списке всех недель года - PullRequest
0 голосов
/ 29 октября 2019

У меня есть приложение ASP.net C #, которое создает список всех недель в данном году. например, выбранный год 2019, и будет производиться с 31/12/2019 по 01/01/2019 и так далее. см. прикрепленное изображение. enter image description here

Для этого я заимствую некоторый код из примера, который я нашел в переполнении стека здесь

Теперь у меня есть еще один списоксодержащий даты в формате дд / мм / гггг, он генерируется из файла XML, поэтому я хотел показать только недели, которые соответствуют датам в списке недель в году, и заполнить раскрывающийся список, когда дата в моем XML сгенерированасписок содержится в нем.

Например, если у меня была целая неделя или даже день в моем сгенерированном XML-списке, который попал в период с 31/12/2018 по 01/01/2019, я хочу показать его ввыпадающий список. Точно так же, если сгенерированный XML-список не содержит хотя бы одного дня с той недели, не показывайте его.

Я вставил код, который использовал, чтобы получить недели данного года ниже.

Я не уверен, есть ли простой способ сравнить оба списка. Любая помощь будет принята с благодарностью.

public List<string> FetchWeeks(int year)
{
    List<string> weeks = new List<string>();
    DateTime startDate = new DateTime(year, 1, 1);
    startDate = startDate.AddDays(1 - (int)startDate.DayOfWeek);
    DateTime endDate = startDate.AddDays(6);
    while (startDate.Year < 1 + year)
    {
        weeks.Add(string.Format("{0:dd/MM/yyyy} to {1:dd/MM/yyyy}", startDate, endDate));
        startDate = startDate.AddDays(7);
        endDate = endDate.AddDays(7);

    }
    //DropDownList1.Items.Add(weeks);
    return weeks;
}

Ответы [ 4 ]

0 голосов
/ 29 октября 2019

Используя некоторые функции расширения и LINQ, вы можете просто сгенерировать список непосредственно из XML-даты. List<string>.

Во-первых, расширение IEnumerable<> для выбора различных лямбда-функций:

public static class IEnumerableExt {
    public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> src, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer = null) {
        var seenKeys = new HashSet<TKey>(comparer);
        foreach (var e in src)
            if (seenKeys.Add(keySelector(e)))
                yield return e;
    }
}

Затем некоторые расширения календаря используют встроенные методы ISOWeek для получения недели года (исходя из диапазонов дат недели, я предполагаю, что вы используете недели ISO 8601):

public static class CalendarExt {
    public static int GetISO8601WeekOfYear(this DateTime aDate) => ISOWeek.GetWeekOfYear(aDate);
    public static DateTime FirstDateOfYear(this DateTime d) => new DateTime(d.Year, 1, 1);
    public static DateTime FirstDateOfISO8601Week(this DateTime aDate) => aDate.AddDays(-(((int)aDate.DayOfWeek + 6) % 7));
    public static DateTime LastDateofISO8601Week(this DateTime aDate) => aDate.FirstDateOfISO8601Week().AddDays(6);    
    public static DateTime FirstDateOfISO8601Week(int year, int weekNum) => ISOWeek.ToDateTime(year, weekNum, DayOfWeek.Monday);
    public static DateTime LastDateofISO8601Week(int year, int weekNum) => FirstDateOfISO8601Week(year, weekNum).AddDays(6);    

    // for .Net without ISOWeek
    //public static DateTime FirstDateOfISO8601Week(this DateTime aDate) => aDate.AddDays(-(((int)aDate.DayOfWeek + 6) % 7));
    //public static int GetISO8601WeekOfYear(this DateTime aDate) =>
    //    CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(aDate.AddDays(DayOfWeek.Monday <= aDate.DayOfWeek && aDate.DayOfWeek <= DayOfWeek.Wednesday ? 3 : 0), CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}

Наконец, учитывая ваш список строковых дат из XML в xmlDateStrings, вы можете вычислить список диапазонов недели:

var currentCulture = CultureInfo.CurrentCulture;
var ans = xmlDateStrings.Select(ds => DateTime.ParseExact(ds, "dd/MM/yyyy", currentCulture))
                        .DistinctBy(d => d.GetISO8601WeekOfYear())
                        .OrderBy(d => d) // assume XML is unsorted
                        .Select(d => $"{d.FirstDateOfISO8601Week().ToString("dd/MM/yyyy")} to {d.LastDateofISO8601Week().ToString("dd/MM/yyyy")}")
                        .ToList();
0 голосов
/ 29 октября 2019

Если бы я пытался сравнить списки, чтобы определить набор допустимых недель, я бы попытался определить абсолютный индекс недели и использовать его в своей работе. Поскольку на недели не влияют такие вещи, как високосные годы или другие странные даты, мы можем просто посчитать с 7-дневным интервалом от начала известного диапазона дат. Простите, если мой C # ржавый, но что-то с эффектом:

public int ToWeekIndex(DateTime date)
{
   // Takes any date and maps it to a value that represents the week it resides in.
   Timespan ts = date - DateTime.MinValue // Monday, January 1, 0001;
   return ts.Days / 7; // Integer divide, drops the remainder.
}

public DateTime FromWeekIndex(int weekIndex)
{
   // Takes a week index and returns the Monday from it.
   Timespan ts = new Timespan(weekIndex * 7, 0, 0, 0); // Days, hours, minutes, seconds
   return DateTime.MinValue + ts;
}

Тогда, чтобы построить свои недели, вы могли бы сделать что-то с эффектом псевдокода:

all_weeks = []
for date in January 1, 2019 to December 31, 2019 step 7 days:
   week_index = ToWeekIndex(date)
   week_start = FromWeekIndex(week_index)
   week_end = week_start + 7 days - 1 second
   all_weeks += [week_start, week_end]
0 голосов
/ 29 октября 2019

Это недели в данных года, которые у вас уже есть -

        class WeekData
        {
            public DateTime WeekStartDate { get; set; }
            public DateTime WeekEndDate { get; set; }

            public int WeekStartDay //Gets Day in the year for the Week Start Date
            {
                get { return WeekStartDate.DayOfYear; }
            }

            public int WeekEndDay //Gets Day in the year for the Week End Date
            {
                get { return WeekEndDate.DayOfYear; }
            }
        }

Dummy WeeksInTheYear data

            List<WeekData> weeks = new List<WeekData>
            {
                new WeekData{WeekStartDate = new DateTime(2019,10,6), WeekEndDate = new DateTime(2019,10,12)},
                new WeekData{WeekStartDate = new DateTime(2019,10,13), WeekEndDate = new DateTime(2019,10,19)},
                new WeekData{WeekStartDate = new DateTime(2019,10,20), WeekEndDate = new DateTime(2019,10,26)},
                new WeekData{WeekStartDate = new DateTime(2019,10,27), WeekEndDate = new DateTime(2019,11,2)}
            };

Dummy Dates из XML-фида

List<DateTime> xmlDates = new List<DateTime> { new DateTime(2019, 11, 1), new DateTime(2019, 10, 12), new DateTime(2019, 10, 31) };

Фильтрация

            var weeksINeed = new List<WeekData>();
            foreach (var date in xmlDates)
            {
                var weekINeed = weeks.Where(x => x.WeekStartDay <= date.DayOfYear && x.WeekEndDay >= date.DayOfYear)
                    .FirstOrDefault();
                if (!weeksINeed.Any(x => x.WeekStartDay == weekINeed.WeekStartDay))
                {
                    weeksINeed.Add(weekINeed);
                }
            }

Вывод -

            foreach (var weekdata in weeksINeed.OrderBy(x=>x.WeekStartDay))
            {
                Console.WriteLine($"WeekStartDate - {weekdata.WeekStartDate} WeekEndDate - {weekdata.WeekEndDate}");
            }

test output

0 голосов
/ 29 октября 2019

вместо списка строк для дат, используйте список объектов, который содержит даты недели и логическое значение по умолчанию false.

public class WeekObj
{
    public string Week { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public bool IsValid { get; set; }
};

List<WeekObj> weeks= new WeekObj();
weeks.add(new WeekObj { "week string", startDate, endDate, false });

Выполните цикл по списку дней и для каждого дня переходитепросмотрите список недель и установите его в значение true, если день находится между startDate и endDate (который теперь находится в DateTime obj), сделайте это для ложных дат, не нужно заново сопоставлять истинные даты.

public static bool Between(DateTime input, DateTime date1, DateTime date2)
{
    return (input >= date1 && input <= date2);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...