Comparing Dates, ignoring year - Linq/Entity Framework - linq

Is there any easy way to compare dates, that ignores year, using Linq and the Entity Framework?
Say I have the following
var result = context.SomeEntity.Where(e => e.SomeDate > startDate);
This is assuming that SomeDate and startDate are .NET DateTime's.
What I would like to do is compare these dates without comparing year. SomeDate can be any year. Is there any easy way to do this? The only way I could think of would be to use the following:
var result = context.SomeEntity(e =>
e.SomeDate.Month > startDate.Month ||
(e.SomeDate.Month == startDate.Month && e.SomeDate.Day >= startDate));
This method quickly gets more complicated if I am looking to have an endDate as well, as I will have to do things like take account for when the start date is at the end of the year and the end date is at the beginning.
Is there any easy way to go about this?
Update:
I ended up just going about it the way I had initially thought in the post... a heck of a lot of code for something conceptually simple. Basically just had to find if a date fell within a range, ignoring year, and looping the calendar if startDate > endDate If anyone knows an easier way, please post as I am still interested.

If you really need to compare only dates (not times) then DateTime.DayOfYear property might help. But you should be careful regarding leap years in this case. Other of this I cannot imagine anything more simple than your approach with comparing months and days.
If all you care about is that this method will become more complicated after introducing second comparison then simple method extraction should help.
Another approach might be creating an extension method which will return a number applicable for your comparison. For example let's call this method GetYearIgnoringOrdinal():
public static int GetYearIgnoringOrdinal(this DateTime date)
{
return date.Month*100 + date.Day;
}
And then use it like this:
var result = context.SomeEntity.Where(e => e.SomeDate.GetYearIgnoringOrdinal() > startDate.GetYearIgnoringOrdinal());

Slightly simpler looking way
var result = context.SomeEntity(e =>
e.SomeDate.Month * 100 + e.SomeDate.Day > startDate.Month * 100 + startDate.Day
);
You could also create a user defined function (assuming SQL server is used) and that function can be used in the query.

Related

very basic pig-latin beginner code

I am new to hadoop and all its derivatives. And I am really getting intimidated by the abundance of information available.
But one thing I have realized is that to start implementing/using hadoop or distributed codes, one has to basically change the way they think about a problem.
I was wondering if someone can help me in the following.
So, basically (like anyone else) I have a raw data.. I want to parse it and extract some information and then run some algorithm and save the results.
Lets say I have a text file "foo.txt" where data is like:
id,$value,garbage_field,time_string\n
1, 200, grrrr,2012:12:2:13:00:00
2, 12.22,jlfa,2012:12:4:15:00:00
1, 2, ajf, 2012:12:22:13:56:00
As you can see that the id can be repeated.This id can be like how much money a customer has spent!!
What I want to do is save the result in a file which contains how much money each of the customer has spent in "morning","afternoon""evening""night"
(You can define your some time buckets to define what morning and all is.
For example here probably
1, 0,202,0,0
1 is the id, 0--> 0$ spent in morning, 202 in afternon, 0 in evening and night
Now I have a python code for it.. But I have to implement this in pig.. to get started.
If anyone can just write/guide me thru this.. Thats all I need to get started.
Thanks
I'd start like this:
foo = LOAD 'foo.txt' USING PigStorage(',') AS (
CUSTOMER_ID:int,
DOLLARS_SPENT:float,
GARBAGE_FIELD,
TIME_STRING:chararray
);
foo_with_timeslots = FOREACH foo {
GENERATE
CUSTOMER_ID,
DOLLARS_SPENT,
/* DO TIME SLOT CALCULATION HERE */ AS TIME_SLOT
;
}
I don't have much knowledge of date/time values in pig, so I'll leave how to do conversion from time string to timeslot, to you.
id_grouped_foo_with_timeslots = GROUP foo_with_timeslots BY (
CUSTOMER_ID,
TIME_SLOT
);
-- Calculate how much each customer spent at time slots
spent_per_customer_per_timeslot = FOREACH id_grouped_foo_with_timeslots {
GENERATE
group.CUSTOMER_ID as CUSTOMER_ID,
group.TIME_SLOT as TIME_SLOT,
SUM(foo_with_timeslots.DOLLARS_SPENT) as TOTAL_SPENT
;
}
You'll have an output like below in spent_per_customer_per_timeslot
1,Morning,200
1,Evening,100
2,Afternoon,30
At this point it should be trivial to re-group the data and put it in the shape you want.

Linq Get 7 days prior to given date

Is it possible to get all 7 days for a given date using linq query, please?
I could use the other methods to populate the list but thought would be wise to use 2 lines of LINQ if possible.
Thanks
Hacky but
IEnumerable<DateTime> getDays(DateTime date) {
return Enumerable.Range(0, 7).Select(n => date.AddDays(-1 * n));
}
Note: didn't test and not positive about the date methods.

How can I compare 2 dates in a Where statement while using NoRM for MongoDB on C#?

I have a table in Mongo. One of the fields is a DateTime. I would like to be able to get all of the records that are only for a single day (i.e. 9/3/2011).
If I do something like this:
var list = (from c in col
where c.PublishDate == DateTime.Now
select c).ToList();
Then it doesn't work because it is using the time in the comparison. Normally I would just compare the ToShortDateString() but NoRM does not allow me to use this.
Thoughts?
David
The best way to handle this is normally to calculate the start datetime and end datetime for the date in question and then query for values in that range.
var start = DateTime.Now.Date;
var end = start.AddDays(1);
...
But you'd also be well advised to switch to the official C# driver now. You should also use UTC datetimes in your database (but that gets more complicated).

Get the the most recent and the one before the most recent item

I have a table with many anniversaries : Date + Name.
I want to display the next anniversary and the one after with Linq.
How can i build the query ?
I use EF
Thanks
John
Just order by date and then use the .Take(n) functionality
Example with a list of some objects assuming you want to order by Date then Name:
List<Anniversaries> annivDates = GetAnnivDates();
List<Anniversaries> recentAnniv = annivDates.OrderBy(d => d.Date).ThenBy(d => d.Name).Take(2).ToList();
If the anniversaries are stored in regular DateTime structs, they may have the 'wrong' year set (i.e. wedding or birth year). I suggest writing a function which calculates the next date for an anniversary (based on the current day) like:
static DateTime CalcNext(DateTime anniversary) {
DateTime newDate = new DateTime(DateTime.Now.Year, anniversary.Month, anniversary.Day);
if (newDate < DateTime.Now.Date)
newDate = newDate.AddYear(1);
return newDate;
}
Then you proceed with sorting the dates and taking the first two values like described in the other postings:
(from e in anniversaries orderby CalcNext(e.Date) select e).Take(2)

DateTime Comparison in LINQ

I am ran into the following issue.
Take a look at the following where clause.
Where(x => x.CreateTS <= dateParameters.CreationDate.ToDateValue &&
x.CreateTS >= dateParameters.CreationDate.FromDateValue)
CreateTS is a Timestamp column in the table. so when my dateparameters are todate = 01/28/2010 12:00A.M" fromdate= "01/26/2010 12.00A.M" (c# DateTime types) my query doesnot retrivies the table records whose CreateTS look like 01/28/2010 1:45A.M and above just differeing in the timestamps.
I just wanted to do comparison and dont want to compare the timestamps. any help would be appreciated.
Just look at the .Date portion of the DateTime:
Where(x => x.CreateTS.Date <= dateParameters.CreationDate.ToDateValue && x.CreateTS.Date >= dateParameters.CreationDate.FromDateValue)
As a side note:
Personally, I would put from first, since it's a bit easier to follow from a readability standpoint:
Where(x => x.CreateTS.Date >= dateParameters.CreationDate.FromDateValue && x.CreateTS.Date <= dateParameters.CreationDate.ToDateValue)
(I find it easier to think of being between two values as being >low and
Edit: You didn't specify that you were using the EF LINQ providers, which do not allow you to do Date. You can, I believe, handle this by looking forward one day, and using < instead of <= for your "to" comparison:
Where(x => x.CreateTS >= dateParameters.CreationDate.FromDateValue && x.CreateTS.Date < dateParameters.CreationDate.AddDays(1).ToDateValue)
#SARAVAN, AFAIK timestamp columns cannot be used in comparisons like that. A timestamp columns are mapped as byte[] (byte array) in EF. If comparisons like that are needed, I suggest to change the timestamp column in database to a datetime one.
only to quote from MSDN:
The SQL Server timestamp data type has nothing to do with times or dates. SQL Server timestamps are binary numbers that indicate the relative sequence in which data modifications took place in a database.
Interesting moment here is that
01/28/2010 12:00A.M actually in 24 hour format is 00:00 while 01/28/2010 1:45A.M is 01:45 and that seems to be the reason why those records are not returned. The midday will be 01/28/2010 12:00P.M

Resources