我一直在尝试根据给定的时间获取句点数组中的标题,描述,开始和结束日期,我有以下JSON数据(以下的变量名是 _json < / EM> ):
更新
我想要做的是在json数组中获取标题,描述,开始和结束日期,它的条件将基于json数组中的开始和结束日期。
[
{
"ID": "1",
"Title": "First Title",
"Description": "First Description",
"Periods": [
{
"StartDate": "2017-04-23 15:30",
"EndDate": "2017-04-23 15:40"
},
{
"StartDate": "2017-04-23 15:42",
"EndDate": "2017-04-23 15:45"
},
{
"StartDate": "2017-04-23 15:47",
"EndDate": "2017-04-23 15:50"
}
]
},
{
"ID" : "2",
"Title": "Second Title",
"Description": "Second Description",
"Periods": [
{
"StartDate": "2017-04-23 15:52",
"EndDate": "2017-04-23 15:55"
},
{
"StartDate": "2017-04-23 15:57",
"EndDate": "2017-04-23 16:00"
},
{
"StartDate": "2017-04-23 16:02",
"EndDate": "2017-04-23 16:05"
}
]
}
]
这是我的代码:
public sealed class Information
{
public List<Period> Periods;
public string Title;
public string Description;
public int ID;
}
public sealed class Period
{
public DateTime StartDate;
public DateTime EndDate;
}
var informations = JsonConvert.DeserializeObject<List<Information>>(_json);
var information = GetData(informations, DateTime.Now);
private Information GetData(List<Information> informations, DateTime dateToCheck)
{
return informations.Select(x =>
{
x.Periods = x.Periods
.TakeWhile(y => dateToCheck >= y.StartDate
&& dateToCheck < y.EndDate)
.ToList();
if (x.Periods.Count > 0)
return x;
else
return null;
}).FirstOrDefault();
}
但是,它只接受JSON数据的第一个数组(ID:1)和JSON数据中 Periods 的第一个数组,甚至 DateTime.Now 超过 2017-04-23 15:40 ,或 2017 -04-23 15:52 ,它将返回null。
我是否过滤不正确的LINQ或在时间条件之间?
你的回答非常感谢。
第二次更新:
预期输出将如下:
拥有JSON数据,例如:日期时间落入“ID:2”和“期间: 2017-04-23 15:57“,那么它只返回 ID no 2 的JSON和下降期间(在这种情况下 2017-04-23 15:57 as StartDate , 2017-04-23 16:00作为EndDate ),同时删除其余的期间。所以它就像这个(它基于时间段,日期时间落在哪里,它将确定需要获得哪些数据)。
"ID" : "2",
"Title": "Second Title",
"Description": "Second Description",
"Periods": [ {
"StartDate": "2017-04-23 15:57",
"EndDate": "2017-04-23 16:00" }
由于
答案 0 :(得分:2)
根据MSDN,您的查询问题为TakeWhile: -
只要指定的条件是,就返回序列中的元素 真正。元素的索引用于谓词的逻辑中 功能
所以在你的查询中它只是检查,直到它找到正确的匹配,然后忽略所有数据。相反,您需要检查整个periods
中的状况。
您可以使用FirstOrDefault
简化查询,它可以为您提供正确的结果: -
return informations.FirstOrDefault(y => dateToCheck >= y.StartDate
& dateToCheck < y.EndDate);
如果找不到匹配项,则返回 null ,否则返回第一个Information
对象(如果找到匹配项)。
如果您想要返回所有匹配的Periods
,请使用Where
instaed,您的方法返回类型应更改为IEnumerable<Information>
而不是Information
。
答案 1 :(得分:1)
我认为您需要TakeWhile
代替Where
:
x.Periods = x.Periods
.Where(y => dateToCheck >= y.StartDate
&& dateToCheck < y.EndDate)
.ToList();
请记住,TakeWhile
在条件为false时停止。如果您需要更正式的解释,可以找到here:
TakeWhile(IEnumerable,Func) 方法通过使用谓词测试源的每个元素并产生 如果结果为true,则为element。枚举在谓词时停止 函数为元素返回false或者source不再包含 元件。
<强>更新强>
private Information GetFirstMatchingInformationByPeriod(
List<Information> informations
, DateTime dateToCheck)
{
// Find the first information that match your search criteria
var information = informations.FirstOrDefault(information
=> information.Periods
.Any(period
=> period.dateToCheck >= period.StartDate
&& period.dateToCheck < period.EndDate);
// If not any found, return null.
if(information == null) return null;
var firstMatchingPeriod = information.Periods
.First(period => dateToCheck >= period.StartDate
&& dateToCheck < period.EndDate);
// Information found.
// Change it's periods with a List containin only the first matching period.
information.Periods = new List<Period>{ firstMatchingPeriod } ;
return information;
}
答案 2 :(得分:0)
有一种更易读的方式来编写查询(有效):
private static Information GetData(List<Information> informations, DateTime dateToCheck)
{
return (from info in informations
from period in info.Periods
where dateToCheck >= period.StartDate &&
dateToCheck < period.EndDate
select info).FirstOrDefault();
}