I was trying to use this solution to count between two times in a csv file.
I tried:
var count = _ais.LoadRecords(Parameters.MinDate, Parameters.MaxDate)
.SkipWhile(record => DateTime.Parse(record.Time).Date != new DateTime(2016, 01, 01,08,00,00))
.TakeWhile(record => DateTime.Parse(record.Time).Date != new DateTime(2016, 01, 01, 09, 00, 00))
.Count();
where record.Time is:
public DateTime Time { get; set; }
The compiler points at record.Time and tells me:
Argument 1: cannot convert from 'System.DateTime' to 'System.ReadOnlySpan<char>'
Is there a way I can use time here?
You don't need to parse your record.Time property.
var count = _ais.LoadRecords(Parameters.MinDate, Parameters.MaxDate)
.SkipWhile(record => record.Time.Date != new DateTime(2016, 01, 01,08,00,00))
.TakeWhile(record => record.Time.Date != new DateTime(2016, 01, 01, 09, 00, 00))
.Count();
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
private void GetTimeBetween()
{
DateTime a = new DateTime(2010, 04, 24, 13, 10, 00);
DateTime b = new DateTime(2010, 04, 25, 13, 10, 00);
Console.WriteLine(b.Subtract(a).TotalMinutes);
double d = b.Subtract(a).TotalMinutes;
}
I'm getting TotalMinutes 1440
But how can i make now that it will create a List with all the dates and time between this two dates between a and b but in jumps of 10 minutes ?
For example in the List the first item will be:
24/4/2010 13:10:00
Then ext item will be
24/4/2010 13:20:00
And so on until b
25/4/2010 13:10:00
In this format in the List or in other formats but the idea to get all the dates+time between the two given dates.
Gee, sometimes its fun to overengineer things. There is an Aggregate function which turns a list into a scalar value - lets create one that goes the other way
public static class Extensions
{
public static IEnumerable<T> Explode<T>(this T value, Func<T,T> next, Func<T,bool> limit)
{
var n = value;
while(!limit(n))
{
yield return n;
n = next(n);
}
}
}
Usage:
DateTime a = new DateTime(2010, 04, 24, 13, 10, 00);
DateTime b = new DateTime(2010, 04, 25, 13, 10, 00);
var result = a.Explode(x => x.AddMinutes(10), x => x>b).ToList();
Live example: http://rextester.com/WCGZL87983
You could loop it:
var list = new List<DateTime>();
var start = new DateTime(2010, 04, 24, 13, 10, 00);
var end = new DateTime(2010, 04, 25, 13, 10, 00);
for (DateTime date = start; date <= end; date = date.AddMinutes(10))
list.Add(date);
Try this
var start = new DateTime(2010, 04, 24, 13, 10, 00);
var end = new DateTime(2010, 04, 25, 13, 10, 00);
for (DateTime date = start; date <= end; date = date.AddMinutes(10))
{
Console.WriteLine(date.ToString("dd/mm/yyyy HH:mm:ss"));
}
Tables dt like this:
index StartDate EndDate
1 2015/03/23 22:00 2015/03/23 23:00
2 2015/03/23 22:00 2015/03/23 22:00
3 2015/03/23 22:00 2015/03/23 22:00
I have set:
lookupedit1.Properties.ValueMember = "StartDate";
lookupedit1.Properties.DisplayMember = "StartDate";
So, the value has show OK, long date Type, but i want the DisplayMemeber like short date type.
I have try any of below, but it's havn't work expectly.
lookupedit1.Properties.Mask.EditMask = "yyyy-MM-dd";
lookupedit1.Properties.DisplayFormat.FormatString = "yyyy-MM-dd";
lookupedit1.Properties.EditFormat.FormatString = "yyyy-MM-dd";
How can i resolve my questions?
i want the DisplayMemeber like short date type
You can use the standard d display-format string for short date (culture specific, described in the Standard Date and Time Format Strings document in MSDN.). To specify formatting-behavior you should add the specific column into the LookUp edit:
lookUpEdit1.Properties.Columns.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo()
{
FieldName = "StartDate",
FormatType = DevExpress.Utils.FormatType.DateTime,
FormatString = "d" // short date
});
lookUpEdit1.Properties.DataSource = new List<Order> {
new Order(){ StartDate = new DateTime(2015, 03, 23, 23, 0, 0) },
new Order(){ StartDate = new DateTime(2015, 03, 24, 23, 0, 0) },
new Order(){ StartDate = new DateTime(2015, 03, 25, 23, 0, 0) },
};
To setup display-behavior while editing you can use the editor's Mask :
lookUpEdit1.Properties.Mask.EditMask = "d"; // short date
lookUpEdit1.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.DateTime;
lookUpEdit1.Properties.Mask.UseMaskAsDisplayFormat = true;
My requirement is to calculate a date based on another date.
The general rules needed for calculation are:
If input date occurs beetwen April 1st and September 30th (any year), the calculated result should be equal to December 31th of the input year
If input date occur between October 1st and March 31th, then the calculated result should be equal to "next" June 30th.
As per those requirements I have this code:
DateTime tmpDate = new DateTime( 2000, inputDate.Month, inputDate.Day );
DateTime aprilDate = new DateTime( 2000, 4, 1 );
DateTime septemberDate = new DateTime( 2000, 9, 30 );
DateTime endofYearDate = new DateTime( 2000, 12, 31 );
DateTime resultDate = DateTime.MaxValue;
if ( tmpDate >= aprilDate && tmpDate <= septemberDate ) {
resultDate = new DateTime( inputDate.Year, 12, 31, 23, 59, 59 );
}
else {
if ( tmpDate > septemberDate && tmpDate <= endofYearDate ) {
resultDate = new DateTime( inputDate.Year, 12, 31, 23, 59, 59 );
}
else {
resultDate = new DateTime( inputDate.Year + 1, 12, 31, 23, 59, 59 );
}
}
However I think that this code it's a little bit messy. How can I write it in a better way?
That looks far two complex:
if ( inputDate.Month > 3 && inputDate.Month < 10 ) {
resultDate = new DateTime( inputDate.Year, 12, 31, 23, 59, 59 );
}
else if (inputDate.Month > 9 ) {
//June, per spec rather than OPs code
resultDate = new DateTime( inputDate.Year + 1, 6, 30, 23, 59, 59 );
} else {
//Ditto
resultDate = new DateTime( inputDate.Year, 6, 30, 23, 59, 59 );
}
However, the presence of the times on these values does concern me. If you're going to be using these values as the end points for particular periods, I'd recommend instead computing the following July or January 1st and then using < comparisons rather than <=. You're far less likely to make mistakes such as excluding events that happen within the last second of the period.
DateTime delayedInputDate = inputDate.AddMonths(3);
if (delayedInputDate.Month < 7)
resultDate = new DateTime(delayedInputDate.Year, 6, 30);
else
resultDate = new DateTime(delayedInputDate.Year, 12, 31);
I want to fetch values from database with specific intervals in C# and need a single query for that.
This is how my Database looks like
Id SensorId Value CreatedOn
------------------------------------------------
1 8 33.5 15-11-2012 5:48 PM
2 5 49.2 15-11-2012 5:48 PM
3 8 33.2 15-11-2012 5:49 PM
4 5 48.5 15-11-2012 5:49 PM
5 8 31.8 15-11-2012 5:50 PM
6 5 42.5 15-11-2012 5:50 PM
7 8 36.5 15-11-2012 5:51 PM
8 5 46.5 15-11-2012 5:51 PM
9 8 39.2 15-11-2012 5:52 PM
10 5 44.4 15-11-2012 5:52 PM
11 8 36.5 15-11-2012 5:53 PM
12 5 46.5 15-11-2012 5:53 PM
13 8 39.2 15-11-2012 5:54 PM
14 5 44.4 15-11-2012 5:54 PM
.. .. ..... ...................
The interval is in minutes.
So, if the interval is 10 minutes, then we need the values at 5:48, 5:58, 6:08 and so on...
I tried doing it with a while loop but it is taking a lot of time as i shoot multiple queries to the database.
Is there any way of getting the data in a single query?
You can use datepart along with a modulus to get the matching rows (eg, #interval = 10, #offset = 8):
SELECT * FROM table
WHERE datepart(minute, CreatedOn) % #interval = #offset
Edit
Note that the above isn't a general solution of selecting by intervals. It will work across hours (and therefore across days) for intervals like 2, 3, 4, 5 ... any minute interval which divides into 60.
If you want to use a strange interval like 7 minutes, then you'd have to define a starting time for the interval and calculate the total minutes for each row, inclusive of hours/days. At that point you'd be best to create an indexed, computed column on the table, based on a user-defined function that calculates the interval in question.
Here is how you can do it, explanation is contained within comments in code:
/*We want 10-minute intervals starting
from minimum date to next day same time*/
DECLARE #startDateTime DATETIME = (
SELECT MIN(CreatedOn)
FROM #yourTable
)
DECLARE #endDateTime DATETIME = DATEADD(DAY, 1, #startDateTime)
DECLARE #startDateTimeTable TABLE (dt DATETIME)
INSERT #startDateTimeTable VALUES (#startDateTime)
/*Create a table that contains relevant datetimes (10-minute
intervals from starting date to end date)*/
;WITH a AS (
SELECT dt
FROM #startDateTimeTable
UNION ALL
SELECT DATEADD(MINUTE, 10, a.dt)
FROM a
JOIN #startDateTimeTable b ON a.dt <= #endDateTime
)
SELECT *
INTO #requiredDateTimes
FROM a
OPTION (MAXRECURSION 32767)
/*Now join data table to datetime table to
filter out only records with datetimes that we want*/
SELECT *
FROM #yourTable a
JOIN #requiredDateTimes b ON
a.CreatedOn = b.dt
Here is an SQL Fiddle
Any of the answers that recommend using modulus (%) are making several assumptions:
You will always have a reading on every sensor at the exact minute in question
You will never have more than one reading in a minute per sensor.
You will never have to deal with intervals smaller than a minute.
These are probably false assumptions, so you need a different approach. First, make a map of all of the time points you are querying over. Then take the last reading from each sensor on or before that point.
Here's a full unit test showing how it can be done in pure linq-to-objects. You may need some minor changes to the query to get it to work in linq-to-sql, but this is the right approach. I used the exact sample data you provided.
As an aside - I hope you are recording your CreatedOn dates in UTC, or you will have ambiguity of sensor readings during daylight savings time "fall-back" transitions. You need to record as DateTime in UTC, or using DateTimeOffset. Either are an appropriate representation of instantaneous time. A DateTime with .Kind of Local or Unspecified is only a valid representation of calendar time, which is not appropriate for sensor readings.
[TestClass]
public class LinqIntervalQueryTest
{
public class Item
{
public int Id { get; set; }
public int SensorId { get; set; }
public double Value { get; set; }
public DateTime CreatedOn { get; set; }
}
[TestMethod]
public void Test()
{
var data = new[]
{
new Item { Id = 1, SensorId = 8, Value = 33.5, CreatedOn = new DateTime(2012, 11, 15, 17, 48, 0, DateTimeKind.Utc) },
new Item { Id = 2, SensorId = 5, Value = 49.2, CreatedOn = new DateTime(2012, 11, 15, 17, 48, 0, DateTimeKind.Utc) },
new Item { Id = 3, SensorId = 8, Value = 33.2, CreatedOn = new DateTime(2012, 11, 15, 17, 49, 0, DateTimeKind.Utc) },
new Item { Id = 4, SensorId = 5, Value = 48.5, CreatedOn = new DateTime(2012, 11, 15, 17, 49, 0, DateTimeKind.Utc) },
new Item { Id = 5, SensorId = 8, Value = 31.8, CreatedOn = new DateTime(2012, 11, 15, 17, 50, 0, DateTimeKind.Utc) },
new Item { Id = 6, SensorId = 5, Value = 42.5, CreatedOn = new DateTime(2012, 11, 15, 17, 50, 0, DateTimeKind.Utc) },
new Item { Id = 7, SensorId = 8, Value = 36.5, CreatedOn = new DateTime(2012, 11, 15, 17, 51, 0, DateTimeKind.Utc) },
new Item { Id = 8, SensorId = 5, Value = 46.5, CreatedOn = new DateTime(2012, 11, 15, 17, 51, 0, DateTimeKind.Utc) },
new Item { Id = 9, SensorId = 8, Value = 39.2, CreatedOn = new DateTime(2012, 11, 15, 17, 52, 0, DateTimeKind.Utc) },
new Item { Id = 10, SensorId = 5, Value = 44.4, CreatedOn = new DateTime(2012, 11, 15, 17, 52, 0, DateTimeKind.Utc) },
new Item { Id = 11, SensorId = 8, Value = 36.5, CreatedOn = new DateTime(2012, 11, 15, 17, 53, 0, DateTimeKind.Utc) },
new Item { Id = 12, SensorId = 5, Value = 46.5, CreatedOn = new DateTime(2012, 11, 15, 17, 53, 0, DateTimeKind.Utc) },
new Item { Id = 13, SensorId = 8, Value = 39.2, CreatedOn = new DateTime(2012, 11, 15, 17, 54, 0, DateTimeKind.Utc) },
new Item { Id = 14, SensorId = 5, Value = 44.4, CreatedOn = new DateTime(2012, 11, 15, 17, 54, 0, DateTimeKind.Utc) },
};
var interval = TimeSpan.FromMinutes(3);
var startDate = data.First().CreatedOn;
var endDate = data.Last().CreatedOn;
var numberOfPoints = (int)((endDate - startDate + interval).Ticks / interval.Ticks);
var points = Enumerable.Range(0, numberOfPoints).Select(x => startDate.AddTicks(interval.Ticks * x));
var query = from item in data
group item by item.SensorId
into g
from point in points
let itemToUse = g.LastOrDefault(x => x.CreatedOn <= point)
orderby itemToUse.CreatedOn, g.Key
select new
{
itemToUse.CreatedOn,
itemToUse.Value,
SensorId = g.Key
};
var results = query.ToList();
Assert.AreEqual(6, results.Count);
Assert.AreEqual(data[1].CreatedOn, results[0].CreatedOn);
Assert.AreEqual(data[1].Value, results[0].Value);
Assert.AreEqual(data[1].SensorId, results[0].SensorId);
Assert.AreEqual(data[0].CreatedOn, results[1].CreatedOn);
Assert.AreEqual(data[0].Value, results[1].Value);
Assert.AreEqual(data[0].SensorId, results[1].SensorId);
Assert.AreEqual(data[7].CreatedOn, results[2].CreatedOn);
Assert.AreEqual(data[7].Value, results[2].Value);
Assert.AreEqual(data[7].SensorId, results[2].SensorId);
Assert.AreEqual(data[6].CreatedOn, results[3].CreatedOn);
Assert.AreEqual(data[6].Value, results[3].Value);
Assert.AreEqual(data[6].SensorId, results[3].SensorId);
Assert.AreEqual(data[13].CreatedOn, results[4].CreatedOn);
Assert.AreEqual(data[13].Value, results[4].Value);
Assert.AreEqual(data[13].SensorId, results[4].SensorId);
Assert.AreEqual(data[12].CreatedOn, results[5].CreatedOn);
Assert.AreEqual(data[12].Value, results[5].Value);
Assert.AreEqual(data[12].SensorId, results[5].SensorId);
}
}
Here's how you can do it in two calls to the database (untested):
int interval = 10;
DateTime firstDate = db.Items.Select(x => x.CreatedOn).Min();
var items = db.Items.Where(x => (x.CreatedOn - firstDate).TotalMinutes % interval == 0).ToList();