I have a list of DateTime values with dates that contain hours and minutes:
List<DateTime> times = times = new List<DateTime>()
{
new DateTime(2019, 01, 01, 17, 00, 00),
new DateTime(2019, 01, 01, 18, 45, 00),
new DateTime(2019, 01, 01, 19, 00, 00),
new DateTime(2019, 01, 01, 19, 30, 00),
new DateTime(2019, 01, 01, 22, 30, 00)
};
DateTime current = DateTime.Now;
I put them all in a ComboBox, and I want to make some sort of algorithm so when I load my form, it will check for the current time and find the closest value to the current time and select the ComboBox item that contains that hour.
How can I achieve this? I tried to loop through them all and check for the least hour, but that doesn't seem to work. Is there a smarter way to do it?
For example: If the current time is 17:32, it will choose 17:00, because that's the closest. But, if the current time is 18:20, it will choose 18:45 and so on.
Compare to the Ticks property of DateTime (MSDN). It can be seen as a linear representation of the whole date and timestamp and is sortable.
Do something like
comboBox.SelectedItem = times.OrderBy(t => Math.Abs(t.Ticks - current.Ticks)).First()
You could take the difference with DateTime.Now for all your datetimes, order by this difference and take the first result.
times.OrderBy(m => Math.Abs((DateTime.Now - m).TotalMilliseconds)).First();
You would have to select an instance of DateTime which minimizes the temporal distance to the current time. You could use an extension method for IEnumerable<T> to do that as follows.
public static T ArgMin<T, R>(T t1, T t2, Func<T, R> f)
where R : IComparable<R>
{
return f(t1).CompareTo(f(t2)) > 0 ? t2 : t1;
}
public static T ArgMin<T, R>(this IEnumerable<T> Sequence, Func<T, R> f)
where R : IComparable<R>
{
return Sequence.Aggregate((t1, t2) => ArgMin<T, R>(t1, t2, f));
}
var iNow = DateTime.Now;
var iResult = times.ArgMin(iTime => Math.Abs((iTime - iNow).Ticks));
Although very generic, this implementation does not involve any sorting.
You are looking for ArgMax which is not implemented in standard Linq, but can be emulated via Aggreagte
List<DateTime> times = new List<DateTime>() {
new DateTime(2019, 01, 01, 17, 00, 00),
new DateTime(2019, 01, 01, 18, 45, 00),
new DateTime(2019, 01, 01, 19, 00, 00),
new DateTime(2019, 01, 01, 19, 30, 00),
new DateTime(2019, 01, 01, 22, 30, 00),
};
DateTime toFind = new DateTime(2019, 5, 8, 18, 20, 0);
var closestTime = times
.Aggregate((best, item) => Math.Abs((item.TimeOfDay - toFind.TimeOfDay).Ticks) <
Math.Abs((best.TimeOfDay - toFind.TimeOfDay).Ticks)
? item
: best);
Please, note, that if we should find the closest time, we have to get rid of date part - TimeOfDay. If date part should be count, just remove TimeOfDay -
var closestDateAndTime = times
.Aggregate((best, item) => Math.Abs((item - toFind).Ticks) <
Math.Abs((best - toFind).Ticks)
? item
: best);
One option is to use MoreLinq's MinBy:
var actualNow = DateTime.Now;
// set `current` up however you need it
var current = new DateTime(2019, 01, 01, actualNow.Hour, actualNow.Minute, actualNow.Minute, actualNow.Millisecond); // set this up however you need it
var min = times.MinBy(z => Math.Abs((current - z).Ticks)).First();
It avoids the memory pressure of the OrderBy based solutions (since it avoids allocating a list to store the entire set of times).
Note you may want to check whether times is empty before using this (or other) solutions. If you don't wish to do that, consider using:
var min = times.MinBy(z => Math.Abs((current - z).Ticks)).Cast<DateTime?>().FirstOrDefault();
which will return null (rather than default(DateTime), or throw an exception) if times is empty.
Related
I have a small problem because I do not always understand how to use the lessons of the day, for example, I want the time from the list to have the day time recalculated from that date, but if I have a new time, that conversion counts from the new time. It works fine for me if I only have one time, but if I have two times, foreach the loop calculates me both times for the day.
This is my code:
public TimeSpan GetHoursForDay(DateTime day) {
TimeSpan time = TimeSpan.Zero;
foreach (var times in shouldWorkTime)
{
if (times.Valid_from > day) //here's the real problem for me, do i want the hours to count from that date, for example: for 1.1.2020 it doesn't need to take hours from 1.12.2019
continue;
if (day.DayOfWeek == DayOfWeek.Monday)
{
time += times.ShouldWorkMonday;
}
if (day.DayOfWeek == DayOfWeek.Tuesday)
{
time += times.ShouldWorkTuesday;
}
if (day.DayOfWeek == DayOfWeek.Wednesday)
{
time += times.ShouldWorkWednesday;
}
if (day.DayOfWeek == DayOfWeek.Thursday)
{
time += times.ShouldWorkThursday;
}
if (day.DayOfWeek == DayOfWeek.Friday)
{
time += times.ShouldWorkFriday;
}
if (day.DayOfWeek == DayOfWeek.Saturday)
{
time += times.ShouldWorkSaturday;
}
if (day.DayOfWeek == DayOfWeek.Sunday)
{
time += times.ShouldWorkSunday;
}
}
return time;
}
}
These are the values I get in the list:
var shouldWorkTime = new List<ShouldWorkTime>
{
new ShouldWorkTime
{
Valid_from = new DateTime(2019, 12, 01, 0, 0, 0),
ShouldWorkMonday = new TimeSpan(8,0,0),
ShouldWorkTuesday= new TimeSpan(7,0,0),
ShouldWorkWednesday= new TimeSpan(6,0,0),
ShouldWorkThursday= new TimeSpan(5,0,0),
ShouldWorkFriday= new TimeSpan(8,0,0),
ShouldWorkSaturday = new TimeSpan(0,0,0),
ShouldWorkSunday = new TimeSpan(0,0,0)
},
new ShouldWorkTime
{
Valid_from = new DateTime(2020, 01, 01, 0, 0, 0),
ShouldWorkMonday = new TimeSpan(4,0,0),
ShouldWorkTuesday= new TimeSpan(3,0,0),
ShouldWorkWednesday= new TimeSpan(6,0,0),
ShouldWorkThursday= new TimeSpan(5,0,0),
ShouldWorkFriday= new TimeSpan(9,0,0),
ShouldWorkSaturday = new TimeSpan(0,0,0),
ShouldWorkSunday = new TimeSpan(0,0,0)
}
};
for the day value, I always get for the current day from the calendar, so I want to be counted in this case for the days of 1.1.2020 values for the days that fall in the second count, and until then the values that fall in the first count.
so i need to return how many hours for a particular day a worker needs to make, but valid from the last date from (Valid_From).
How can I correct this? thank you all very much for your help
eg:
input 1.1.2020 output = 6,0,0;
input 1.12.2019 output = 0,0,0;
Here is a little modification of the Data structure.
Instead of a brunch of property The TimeSpan will be mapped to the DayOfWeek using a Dictionary. This will remove the need for a switch-case or a lot of If.
Using DayOfWeek as dictionary key ensure that only one TimeSpan is defined for a day.
public class WorkingTimeScheldure
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public Dictionary<DayOfWeek, TimeSpan> Scheldure { get; set; }
}
That way I can ask for the TimeSpan of a day using : Scheldure[test.DayOfWeek]
Note the addition of an End property. It may be usefull to select the right thing.
eg: 30/01/2020 is superior to 01/12/2019 and 01/01/2020..
So in order to take the most recent, I assume the list in ordered on Start date and pick the last one: .Last(x => x.Start <= day).
Online Demo
public class Program
{
static List<ShouldWork> WorkTimeScheldure;
public static void Main()
{
WorkTimeScheldure = new List<ShouldWork>
{
new ShouldWork
{
Start = new DateTime(2019, 12, 01, 0, 0, 0),
Scheldure= new Dictionary<DayOfWeek, TimeSpan>()
{
{(DayOfWeek)0, new TimeSpan(0,0,0)},
{(DayOfWeek)1, new TimeSpan(8,0,0)},
{(DayOfWeek)2, new TimeSpan(7,0,0)},
{(DayOfWeek)3, new TimeSpan(6,0,0)},
{(DayOfWeek)4, new TimeSpan(5,0,0)},
{(DayOfWeek)5, new TimeSpan(8,0,0)},
{(DayOfWeek)6, new TimeSpan(0,0,0)}
}
},
new ShouldWork
{
Start = new DateTime(2020, 01, 01, 0, 0, 0),
Scheldure = new Dictionary<DayOfWeek, TimeSpan>()
{
{(DayOfWeek)0, new TimeSpan(0,0,0)},
{(DayOfWeek)1, new TimeSpan(4,0,0)},
{(DayOfWeek)2, new TimeSpan(3,0,0)},
{(DayOfWeek)3, new TimeSpan(6,0,0)},
{(DayOfWeek)4, new TimeSpan(5,0,0)},
{(DayOfWeek)5, new TimeSpan(9,0,0)},
{(DayOfWeek)6, new TimeSpan(0,0,0)}
}
}
};
var testValues = new[] {
new DateTime(2019, 12, 01, 0, 0, 0),
new DateTime(2019, 12, 02, 0, 0, 0),
new DateTime(2019, 12, 03, 0, 0, 0),
new DateTime(2019, 12, 04, 0, 0, 0),
new DateTime(2019, 12, 05, 0, 0, 0),
new DateTime(2019, 12, 06, 0, 0, 0),
new DateTime(2019, 12, 07, 0, 0, 0),
new DateTime(2019, 12, 08, 0, 0, 0),
new DateTime(2020, 01, 01, 0, 0, 0),
new DateTime(2020, 01, 02, 0, 0, 0),
new DateTime(2020, 01, 03, 0, 0, 0),
new DateTime(2020, 01, 05, 0, 0, 0),
new DateTime(2020, 01, 05, 0, 0, 0),
new DateTime(2020, 01, 06, 0, 0, 0),
new DateTime(2020, 01, 07, 0, 0, 0),
new DateTime(2020, 01, 08, 0, 0, 0),
};
foreach (var test in testValues) {
// Perhaps there is many possible, so I took the Last.
var workingTime = WorkTimeScheldure.Last(x => x.Start <= day);
//Please handle the case where there is no matching scheludre for this date.
var houtToWork = workingTime.Scheldure[day.DayOfWeek].Hours;
Console.WriteLine(
$"{day.ToShortDateString()} , it's a {day.DayOfWeek}" +
$" I have to work {houtToWork} Hour{(houtToWork>1?"s":"")}!"
);
}
}
}
Result :
12/01/2019 , it's a Sunday I have to work 0 Hour!
12/02/2019 , it's a Monday I have to work 8 Hours!
12/03/2019 , it's a Tuesday I have to work 7 Hours!
12/04/2019 , it's a Wednesday I have to work 6 Hours!
12/05/2019 , it's a Thursday I have to work 5 Hours!
12/06/2019 , it's a Friday I have to work 8 Hours!
12/07/2019 , it's a Saturday I have to work 0 Hour!
12/08/2019 , it's a Sunday I have to work 0 Hour!
01/01/2020 , it's a Wednesday I have to work 6 Hours!
01/02/2020 , it's a Thursday I have to work 5 Hours!
01/03/2020 , it's a Friday I have to work 9 Hours!
01/04/2020 , it's a Saturday I have to work 0 Hour!
01/05/2020 , it's a Sunday I have to work 0 Hour!
01/06/2020 , it's a Monday I have to work 4 Hours!
01/07/2020 , it's a Tuesday I have to work 3 Hours!
01/08/2020 , it's a Wednesday I have to work 6 Hours!
The test times.Valid_from > day is false for all element in shouldWorkTime if the value of day is big enough. That why time can be incremented multiple time.
If you want to increment only once and on the first/last acceptable value of Valid_from, you should ensure that shouldWorkTime is sorted in increasing/decreasing order and ensure that the increment is done only once.
In fact you didn't need increment but just return the corresponding TimeSpan:
public TimeSpan GetHoursForDay(DateTime day) {
// shouldWorkTime should have been sorted once for all at creation.
// This code use the first acceptable Valid_from
// By using OrderByDescending we take the last (in date) entry
var math = shouldWorkTime
.Where(v => day >= v.Valid_from) // We take only valid entry
.OrderByDescending(v => v.Valid_from) // We sort only on valid entry
.FirstOrDefault(); // we take the last (in date) valid entry
if (match == null)
return TimeSpan.Zero;
switch (day.DayOfWeek)
{
case DayOfWeek.Monday:
return match.ShouldWorkMonday;
case DayOfWeek.Tuesday:
return match.ShouldWorkTuesday;
case DayOfWeek.Wednesday:
return match.ShouldWorkWednesday;
case DayOfWeek.Thursday:
return match.ShouldWorkThursday;
case DayOfWeek.Friday:
return match.ShouldWorkFriday;
case DayOfWeek.Saturday:
return match.ShouldWorkSaturday;
case DayOfWeek.Sunday:
return match.ShouldWorkSunday;
}
}
Edit:
To avoid code duplication, the ShouldWorkTime class may provide a GetWorkTimeForDayOfWeek:
public TimeSpan GetWorkTimeForDayOfWeek(DayOfWeek dayOfWeek) {
...
}
And instead of storing seven values in seven fields, you may take a look to collections. I will choose a Dictionary<DayOfWeek, TimeSpan>.
In my app I've a ticker which runs every 5 seconds. I've also an internal clock and I want to detect when the day chages.
To test, I have tried the following code without success:
DateTime A = new DateTime(2019, 6, 20, 23, 58, 29);
DateTime B = new DateTime(2019, 6, 21, 00, 01, 12);
Int32 dd = (B-A).Days; // it returns 0
double dd = (B-A).TotalDays; // it return 0.00002136213
If I check if TotalDays > 0 I succesfully detect the day change but in the follwing case (with a difference of a minute)
DateTime C = new DateTime(2019, 6, 20, 12, 58, 29);
DateTime D = new DateTime(2019, 6, 20, 12, 59, 29);
the compare fails. Since I need to call a method when day changes, with the example above its called every time and I do not want this behevior. Any hint?
compare Date part of DateTime directly
bool isSameDay = (A.Date == B.Date);
Look at only the Date parts
DateTime A = new DateTime(2019, 6, 20, 23, 58, 29);
DateTime B = new DateTime(2019, 6, 21, 00, 01, 12);
Int32 dd = (B.Date-A.Date).Days;
For your ticker why not use TimeSpan variables to complete your comparison. You set 1 static timespan variable to 24 hours (1 day) and then create a secondary one to store the values. You then set your second timespan variable equal to the subtraction of your two days and this would let you know if a day had gone by.
`
TimeSpan newDayReference = new TimeSpan(24,0,0);
TimeSpan comparison;
//These two variables set to show difference.
DateTime A= DateTime.Now.AddDays(-1);
DateTime B = DateTime.Now;
comparison = B - A;
if(comparison > newDayReference){ //success }
`
I have multiple identical length collections, one timestamp collection of type List<DateTime> and several data collections of type List<double>. The values at each index position in the List<double correspond to the respective index position in List<DateTime>.
I want to be able to compress the data in all data collections by a TimeSpan that is applied to the List<DateTime> and groups the timestamps into TimeSpan bins and applies the same grouping to each data collection.
Here is how I currently "compress" a time series of time stamps:
var someTimeStamps = new List<DateTime>();
var compression = TimeSpan.FromHours(1).Ticks;
var compressedTimeStamps = from rawData in someTimeStamps
group rawData by rawData.Ticks / numberTicks
into tickData
select new DateTime(tickData.Key * compression);
How can I adjust the code in order to have the same groupings apply to the data collections List<double> as well? I want to apply a grouping logic of averaging the values within each data group. I am aiming for computational efficiency, memory consumption is not an issue I look to optimize at this point.
For example:
List<DateTime> items: (for simplicity purpose the order of the values below is (year, month, day, hour, minute, second):
(1) 2018, 8, 14, 08, 20, 05
(2) 2018, 8, 14, 08, 45, 25
(3) 2018, 8, 14, 09, 02, 53
(4) 2018, 8, 14, 09, 34, 12
(5) 2018, 8, 14, 09, 44, 12
List<value> items:
(1) 12
(2) 15
(3) 27
(4) 03
(5) 12
Applying a compression of TimeSpan.FromHours(1) the desired outcome for both collections is :
List<DateTime> items:
(1) 2018, 8, 14, 08, 00, 00
(2) 2018, 8, 14, 09, 00, 00
List<double> items (averaging is applied to the items in each group)
(1) 13.5 (avg of 12 and 15)
(2) 14 (avg of 27, 3, and 12)
You can do it by below code
List<DateTime> dateTimes = new List<DateTime>();
dateTimes.Add(new DateTime(2018, 8, 14, 08, 20, 05));
dateTimes.Add(new DateTime(2018, 8, 14, 08, 45, 25));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 02, 53));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 34, 12));
dateTimes.Add(new DateTime(2018, 8, 14, 09, 44, 12));
List<int> ints = new List<int>();
ints.Add(12);
ints.Add(15);
ints.Add(27);
ints.Add(03);
ints.Add(12);
var averages = dateTimes.Select((k, v) => new { k, v })
.GroupBy(x => new DateTime(x.k.Year, x.k.Month, x.k.Day, x.k.Hour, 0, 0))
.ToDictionary(g => g.Key, g => g.Select(x => ints.ElementAt(x.v)).Average());
Output:
Edit:
If you want your data to be separated into two list like List<DateTime> and List<double> then you can project above dictionary to separated list of keys and values. like
List<DateTime> dateTimeList = averages.Keys.ToList();
List<double> valuesList = averages.Values.ToList();
If I understood you correctly
expand that problem to one time stamp series but multiple data series
var grouped = dateTimes
.Zip(ints, (k, v) => new { k, v })
.GroupBy(g => new DateTime(g.k.Year, g.k.Month, g.k.Day, g.k.Hour, 0, 0), g => g.v);
The above code gives you the compression of your datetime and wrt mulptiple data series
Try once may it help you.
I decided to go with a classic iteration over each data point as it only requires one single iteration regardless of the number of data collections (credits to a friend of mine who suggested to profile this approach):
public void CompressData(TimeSpan compression)
{
//declare generic buffer value function (bid/ask here)
var bufferFunction = new Func<int, double>(index => (Bid[index] + Ask[index]) / 2);
Open = new List<double>();
High = new List<double>();
Low = new List<double>();
Close = new List<double>();
var lastCompTs = -1L;
var dataBuffer = new List<double>();
var timeStamps = new List<DateTime>();
for (int i = 0; i < TimeStamps.Count; ++i)
{
var compTs = TimeStamps[i].Ticks / compression.Ticks;
if (compTs == lastCompTs)
{
//same timestamp -> add to buffer
dataBuffer.Add(bufferFunction(i));
}
else
{
if (dataBuffer.Count > 0)
{
timeStamps.Add(new DateTime(compTs * compression.Ticks));
Open.Add(dataBuffer.First());
High.Add(dataBuffer.Max());
Low.Add(dataBuffer.Min());
Close.Add(dataBuffer.Last());
}
lastCompTs = compTs;
dataBuffer.Clear();
}
}
if (dataBuffer.Count > 0)
{
timeStamps.Add(new DateTime(lastCompTs * compression.Ticks));
Open.Add(dataBuffer.First());
High.Add(dataBuffer.Max());
Low.Add(dataBuffer.Min());
Close.Add(dataBuffer.Last());
}
//assign time series collection
TimeStamps = timeStamps;
}
I need to filter the data from Dictionary<DateTime, int> to get only elements in which difference between subsequent DateTime's is 1 minute or more.
For example, in dictionary I could have such pairs of data:
var pairs = new Dictionary<DateTime, int>()
{
{ new DateTime(2010, 01, 20, 19, 05, 00), 10 },
{ new DateTime(2010, 01, 20, 19, 05, 19), 11 },
{ new DateTime(2010, 01, 20, 19, 05, 49), 12 },
{ new DateTime(2010, 01, 20, 19, 06, 05), 13 },
{ new DateTime(2010, 01, 20, 19, 07, 05), 14 },
{ new DateTime(2010, 01, 20, 19, 07, 55), 15 },
};
And what I would like as a result of filtering is:
<2010-01-20 19:05:00, 10>
<2010-01-20 19:06:05, 13>
<2010-01-20 19:07:05, 14>`
DateTime keys in dictionary are in ascending order so there is no need to reorder, but I would need it to be quite efficent because a lot of data is going to be processed.
Can you introduce me some nice piece of LINQ query to do that?
I'd say this is a bad candidate for Linq. I would go for a straightforward enumerator:
public static IEnumerable<KeyValuePair<DateTime, int>> Filter(IEnumerable<KeyValuePair<DateTime, int>> values)
{
KeyValuePair<DateTime, int>? previous = null;
foreach (var kvp in values.OrderBy(v => v.Key))
{
if (previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1)
{
previous = kvp;
yield return kvp;
}
}
}
Then just enumerate it and do whatever you need with the result:
foreach (var value in Filter(dictionary))
{
Console.WriteLine($"{value.Key} - {value.Value}");
}
Just for fun, a Linq version (please, please, please don't use it):
public static IEnumerable<KeyValuePair<DateTime, int>> FilterLinq(IEnumerable<KeyValuePair<DateTime, int>> values)
{
KeyValuePair<DateTime, int>? previous = null;
return from kvp in values
orderby kvp.Key
where previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1
select (previous = kvp).Value;
}
I would suggest that LINQ is a good choice here. It's usually easy to maintain and more often than not any performance loss is negligible.
Try this:
var filtered =
pairs.Skip(1).Aggregate(pairs.Take(1).ToList(), (a, p) =>
{
if (p.Key.Subtract(a.Last().Key).TotalMinutes >= 1.0)
{
a.Add(p);
}
return a;
}).ToList();
This gives:
I'm trying to seed a database with two lists. The first list is just a bunch of items. The second list is a bunch of junk that references the first list. I'm trying to reference items from first list in the second list of junk, via LINQ, but I'm fairly certain I'm not doing it right:
For example, List 1:
var items = new List<Item>()
{
new Item { ItemtId = 1, DateTime = new DateTime(2014, 09, 05, 12, 30, 30), Text = "Cheese" },
new Item { ItemtId = 1, DateTime = new DateTime(2014, 09, 05, 12, 30, 30), Text = "Lettuce" },
new Item { ItemtId = 1, DateTime = new DateTime(2014, 09, 05, 12, 30, 30), Text = "Ground Beef" },
new Item { ItemtId = 1, DateTime = new DateTime(2014, 09, 03, 12, 30, 30), Text = "Ketchup" },
new Item { ItemtId = 1, DateTime = new DateTime(2014, 09, 03, 12, 30, 30), Text = "Mustard" },
};
var junk= new List<Junk>()
{
new Junk { JunkId = 1, DateTime = new DateTime(2014, 09, 05, 10, 00, 00), Items = items.Where(d => d.DateTime.ToShortDateString() == new DateTime(2014, 09, 05).ToShortDateString()},
new Junk { JunkId = 2, DateTime = new DateTime(2014, 09, 03, 11, 00, 00), Items = items.Where(d => d.DateTime.ToShortDateString() == new DateTime(2014, 09, 03).ToShortDateString()}
};
This seems like it should be the answer to me, because I'm only interested in the date and not the time, but it doesn't seed like this. I get the error:
LINQ to Entities does not recognize the method 'System.String
ToShortDateString()' method, and this method cannot be translated into
a store expression.
Any thoughts on how to build a better solution?
UPDATE
Looks like I didn't transcribe my code accurately to the site, and ended up finding my problem.
In my original code, I had:
new Junk { JunkId = 1, DateTime = new DateTime(2014, 09, 05, 10, 00, 00), Items = context.Items.Where(d => d.DateTime.Date == new DateTime(2014, 09, 05) }
When I should have had
new Junk { JunkId = 1, DateTime = new DateTime(2014, 09, 05, 10, 00, 00), Items = items.Where(d => d.DateTime.Date == new DateTime(2014, 09, 05) }
I'd been flirting with .ToShortDateString() unnecessarily
Change filter to:
.Where(d => d.DateTime.Date == new DateTime(2014, 09, 05))
You can use TruncateTime function of EntityFunctions Class.
new Junk { JunkId = 1, DateTime = new DateTime(2014, 09, 05, 10, 00, 00), Items = items.Where(d => EntityFunctions.TruncateTime(d.DateTime) == EntityFunctions.TruncateTime(new DateTime(2014, 09, 05))}
Note: If you using EntityFramework 6 then it should be System.Data.Entity.DbFunctions.TruncateTime(...) method from EntityFramework.dll.
Your subquery (the Items = part of the Junk variable) isn't a list but an enumerable, so it doesn't get materialized untill it's enumerated, and it's not enumerated untill you use it, down the road, in your linq to entities query.
If you change it as such :
var junk= new List<Junk>()
{
new Junk { JunkId = 1, DateTime = new DateTime(2014, 09, 05, 10, 00, 00), Items = items.Where(d => d.DateTime.ToShortDateString() == new DateTime(2014, 09, 05).ToShortDateString()).ToList()}, // this one will work as it gets materialized right now, not later, so by the time you pass it to linq to entities later it will already be a simple list of diferences, it won't try to compute "toshortdatestring" later, that will already be done
new Junk { JunkId = 2, DateTime = new DateTime(2014, 09, 03, 11, 00, 00), Items = items.Where(d => d.DateTime.ToShortDateString() == new DateTime(2014, 09, 03).ToShortDateString()}
};