преобразование строки данных во время с помощью Linq

#c# #asp.net #linq

#c# #asp.net #linq

Вопрос:

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

350-659, 1640-2119, 2880-3479;

 The output id like is 
M 5:50am - 10:59am
T 3:20am - 10:59am
W 12:00am - 9:59am
etc....

Ranges - 
    Mon= 0-1439
    Tue = 1440-2879
    Wed = 2880 - 4319
    Thurs = 4321 - 5759
    Fri = 5760 - 7199
    Sat = 7200 - 8639
    Sun = 8640 - 10079
  

Что у меня есть до сих пор, так это

 var days = new[] { 24, 48, 72, 96, 120, 144, 168 };
var numbers = Enumerable.Range(1,7);
var hours = days.ToDictionary(x => (double)x/24, i => (int)I*60);

which outputs 
Key     Value
1       1440 
2       2880
3       4320   
4       5760
5       7200 
6       8640
7      10080
  

Комментарии:

1. Работайте в обратном направлении, напишите функцию, которая выполняет задачу синтаксического анализа, которую вы хотите. Затем напишите функцию, которая перечисляет токены из исходного ввода. Затем напишите код, который передает токены в функцию синтаксического анализа. Затем изучите, как преобразовать этот код, скорее всего, цикл foreach, в проекцию linq. Другими словами, разберите задачу на этапы и проработайте каждый шаг по отдельности.

2. Я думаю, что кто-то некоторое время назад подумал, что это было бы хорошей идеей сделать это. Я думаю, вам также нужно было бы знать, какой сегодня день недели.

3. Кроме того, ваши сопоставления неверны. 1440 — вторник в 00:00, и то же самое для остальных.

4. преобразуйте следующее во времена — времена, когда ? На самом деле в C # нет такого понятия, как время, без даты, которая прилагается к нему. Хорошо, итак, 540 — это «9 утра в понедельник», но на какой неделе какого года вы хотите, чтобы это было?

5. Одна буква за день не сократит его. Есть два Ts и два Ss. Кажется, что вы выдвигаете требования по ходу работы.

Ответ №1:

Я вроде как вообще не понимаю вопроса, но принимаю все, что вы сказали, за чистую монету:

 var times = "350-659, 1640-2119, 2880-3479;"
  .Split(',')                                                     //split to string pairs like "350-659"
  .Select(s => s.Split('-').Select(x => int.Parse(x)).ToArray())  //split stringpairs to two strings like "350" and "659", then parse to ints and store as an array
  .Select(sa =>  new {                                            //turn array ints into dates
        F = new DateTime(0).AddMinutes(sa[0]),                    //date 0 i.e. jan 1 0001 was a monday. add minutes to it to get a time and day
        T = new DateTime(0).AddMinutes(sa[1]   1)                 //add 1 to the end minute otherwise 659 is 10:59pm and you want 11:00am
      }
  )

  .Select(t => 
      $"{($"{t.F:ddd}"[0])} {t.F:hh':'mmtt} - {t.T:hh':'mmtt}"    //format the date to a day name and pull the first character, plus format the dates to hh:mmtt format (eg 09:00AM)
  );
    
    Console.Write(string.Join("rn", times));
  

Если вы действительно хотите работать с этими вещами разумным образом, я рекомендую вам остановиться раньше, чем окончательный выбор, который их упорядочивает, и работать с анонимным типом t , который содержит пару datetimes

Единственное, что в этом выводе не соответствует спецификации, это то, что AM / PM написаны в верхнем регистре. Если это вас беспокоит, подумайте:

 $"{t.F:ddd}"[0]   ($" {t.F:hh':'mmtt} - {t.T:hh':'mmtt}").ToLower()
  

Комментарии:

1. Спасибо, если вы не возражаете, если я спрошу, какое выражение вы использовали в операторе select с помощью $, я все еще новичок в LINQ

2. Это не linq, это интерполяция строк. var x = "Hello"; var y = $"{x} world"; это более аккуратный способ записи var x = "Hello"; var y = string.Format("{0} world", x); , хотя вы не можете повторно использовать параметры, как в строке. Форматирование; если вы хотите что-то в интерполированной строке дважды, вам нужно записать это дважды, поэтому, например, var y = $"{(i < 1 ? "hello":"goodbye")} {(i < 1 ? "hello":"goodbye")} world" может быть не так аккуратно, по вашему мнению, как var y = string.Format("{0} {0} world", (i < 1 ? "hello":"goodbye") .

3. Вероятно, самое аккуратное, что можно сделать при интерполяции, — это создать переменные: var helloOrGoodbye = (i < 1 ? "hello":"goodbye"); var y = $"{helloOrGoodbye} {helloOrGoodbye} world" . Точно так же, как со строкой. Форматирование, заполнитель может принимать строку формата после двоеточия, поэтому var i = 255; var y = $"Hex is: {i:X}" будет форматировать 255 как шестнадцатеричную строку, так же, как вызов i.ToString("X") или string.Format("Hex is: {0:X}", i); будет

4. Я добавил несколько комментариев, объясняющих linq

Ответ №2:

Вы могли бы получить текущий понедельник недели и добавить минуты. Я не думаю, что вы можете сделать это в Linq напрямую.

 //your timestamp
int minutes = 2345;

//get the day of week (sunday = 0)
int weekday = (int)DateTime.Now.DayOfWeek - 1;
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
    weekday = 6;

//get the first day of this week
DateTime firstDayOfWeek = DateTime.Now.AddDays(-1 * weekday);

//add the number of minutes
DateTime date = firstDayOfWeek.Date.AddMinutes(minutes);
  

Ответ №3:

Интервал времени (в отличие от абсолютного момента времени) выражается как промежуток времени. В этом случае у вас будет один временной интервал, который представляет смещение (от начала недели) до времени начала, затем другой временной интервал, который представляет смещение до времени окончания.

Вот как преобразовать вашу строку в последовательность временных интервалов.

 var input = @"540-1019;1980-2459;3420-3899;4860-5339;6300-6779";
var times = input
    .Split(';')
    .Select(item => item.Split('-'))
    .Select(pair => new
    {
        StartTime = new TimeSpan(hours: 0, minutes: int.Parse(pair[0]), seconds: 0),
        EndTime   = new TimeSpan(hours: 0, minutes: int.Parse(pair[1]), seconds: 0)
    })
    .ToList();
foreach (var time in times)
{
    Console.WriteLine
    (
        @"Day: {0} Start: {1:h:mm} End: {2:h:mm}",
        time.StartTime.Days, 
        time.StartTime,
        time.EndTime
    );
}
  

Вывод:

 Day: 0 Start: 9:00 End: 16:59
Day: 1 Start: 9:00 End: 16:59
Day: 2 Start: 9:00 End: 16:59
Day: 3 Start: 9:00 End: 16:59
Day: 4 Start: 9:00 End: 16:59
  

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