Title: converting data string to time using Linq
Tags: c#;asp.net;linq
Question: How can I convert the following into times, knowing that the values are the number of minutes.
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
```
What I have so far is
```var days = new[] { 24, 48, 72, 96, 120, 144, 168 };
var numbers = Enumerable.Range(1,7);
var hours = days.ToDictionary(x =&gt; (double)x/24, i =&gt; (int)I*60);

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

Comment: *convert the following into times* - times *when* ? There isn't really any such thing as a Time in C# without a date that comes with it. OK, so 540 is "9am on Monday", but *what week of what year* do you want it to be?

Comment: Why the imposition of "using LINQ"? LINQ is for querying things, and doesn't *really* make sense in this context, which is "parse a string to a list of ints and interpret them as the number of minutes since midnight on monday". Is this an academic exercise where you *must* use LINQ in some way, however tenuous? Are you aware that 1019 minutes since midnight is 4:59 pm and not 5pm? Are we supposed to factor for this in an answer?

Comment: Work backwards, Write a function that does the parsing task you want. Then write a function that enumerates the tokens from the source input. Then write  code that passes the tokens to the parsing function. Then examine how to convert that code, most likely a foreach loop, into a linq projection. In other words take the task apart into steps, and work each step individually.

Comment: What do you want the output to look like? Maybe give an example of a couple of input values and the expected output values. For example: "0065 should give an output of Monday 1:05 AM"

Comment: I guess somebody, some time ago, thought it would be a good idea to do this. I think you would also need to know what day of the week it is.

Comment: Also, your mappings are incorrect. 1440 is Tuesday at 00:00, and same for the rest.

Comment: One letter for day won't cut it. There are two Ts and two Ss. It seems as though you are coming up with the requirements as you go.

Here is the accepted answer: I kinda don't get the question at all, but taking everything you've said at face value:
```var times = &quot;350-659, 1640-2119, 2880-3479;&quot;
  .Split(',')                                                     //split to string pairs like &quot;350-659&quot;
  .Select(s =&gt; s.Split('-').Select(x =&gt; int.Parse(x)).ToArray())  //split stringpairs to two strings like &quot;350&quot; and &quot;659&quot;, then parse to ints and store as an array
  .Select(sa =&gt;  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 =&gt; 
      $&quot;{($&quot;{t.F:ddd}&quot;[0])} {t.F:hh':'mmtt} - {t.T:hh':'mmtt}&quot;    //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(&quot;\r\n&quot;, times));
```
If you actually want to work with these things in a sensible way I recommend you stop sooner than the final Select, which stringifies them, and work with the anonymous type ```t``` that contains a pair of datetimes
The only thing about this output that doesn't match the spec, is that the AM/PM are uppercase. If that bothers you, consider:
```$&quot;{t.F:ddd}&quot;[0] + ($&quot; {t.F:hh':'mmtt} - {t.T:hh':'mmtt}&quot;).ToLower()
```

Comment for this answer: That's not a linq thing, it's string interpolation. `var x = "Hello"; var y = $"{x} world";` is a neater way of writing `var x = "Hello"; var y = string.Format("{0} world", x);` though you can't reuse parameters like in string.Format; if you want something in an interpolated string twice you have to write it twice so eg `var y = $"{(i < 1 ? "hello":"goodbye")} {(i < 1 ? "hello":"goodbye")} world"` might not be as neat in your opinion as `var y = string.Format("{0} {0} world", (i < 1 ? "hello":"goodbye")`.
Comment for this answer: Probably the neatest thing to do if interpolating is to make variables: `var helloOrGoodbye = (i < 1 ? "hello":"goodbye"); var y = $"{helloOrGoodbye} {helloOrGoodbye} world"`. Just like with string.Format, a placeholder can accept a format string after a colon, so `var i = 255; var y = $"Hex is: {i:X}"` will format 255 as a hex string, same as calling `i.ToString("X")` or `string.Format("Hex is: {0:X}", i);` would
Comment for this answer: I added some comments to explain the linq
Comment for this answer: Thank you, if you don't mind me asking, what kind of expression is it that you used in the select statement with the $, I'm still new to LINQ

Here is another answer: An interval of time (as opposed to an absolute point in time) is expressed as a TimeSpan. In this case, you'd have one TimeSpan that represents the offset (from the beginning of the week) until the starting time, then another TimeSpan that represents the offset to the end time.
Here's how to convert your string into a series of TimeSpans.
```var input = @&quot;540-1019;1980-2459;3420-3899;4860-5339;6300-6779&quot;;
var times = input
    .Split(';')
    .Select(item =&gt; item.Split('-'))
    .Select(pair =&gt; 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
    (
        @&quot;Day: {0} Start: {1:h\:mm} End: {2:h\:mm}&quot;,
        time.StartTime.Days, 
        time.StartTime,
        time.EndTime
    );
}
```
Output:
```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
```
You can of course choose to format the TimeSpan in any way you want using the appropriate format string.


Here is another answer: You could get the current monday of the week and add the minutes. I don't think you can do this in Linq directly.
```//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);
```


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 3, 'CommentCount': 7, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2020:00:09/03/20', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<c#><asp.net><linq>', 'Title': 'converting data string to time using Linq', 'ViewCount': 182, 'id': 63728762, 'user_AboutMe': None, 'user_AccountId': 19416282.0, 'user_DisplayName': 'John Michaelson', 'user_Reputation': 5.0, 'user_Views': 5.0, 'user_id': 14199671.0}}