Linq-to-EF DateTime.ToLocalTime not supported - c#

DateTime.ToLocalTime is not supported in Linq to EF.
What's the alternative? I am running out of idea.

Instead of using .ToLocalTime() inside your Linq query, use the opposite conversion outside of the query on the parameters.
var dateUniversal = dateParam.ToUniversalTime();
var query = myTable.Where( t => t.DateTime > dateUniversal );

I used a combination of Extensions plus relying on the value passed from the front-end of my app to be in LocalTime. So, If I had two date times.. like.. a start date and end date parameter for a report, I'd put them up there.. let the user submit in LocalTime.. then on the back end part of my Controller.. I'd use the sdate and edate variables in my Linq to Entities Query. The static extension methods I threw into a static helper class. Sorry that I'm over a year late. : )
DateTime sdate = CalcHelper.AbsoluteStart(model.StartDate);
DateTime edate = CalcHelper.AbsoluteEnd(model.EndDate);
public static DateTime AbsoluteStart(this DateTime dateTime)
{
return dateTime.Date.ToUniversalTime();
}
public static DateTime AbsoluteEnd(this DateTime dateTime)
{
return AbsoluteStart(dateTime).AddDays(1).AddTicks(-1).ToUniversalTime();
}

if you get the timezone offset from the server you might be able to use EntityFunctions to apply the offset in your linq query
var offset = TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes;
var result = db.Dates.Where(a =>
EntityFunctions.DiffDays(EntityFunctions.AddMinutes(a.Date, offset), DateTime.Now) == 0);

You can try like this:
var promotions = _promotionService.GetAll(
x => (DbFunctions.TruncateTime(x.CreatedDate.Value) >= viewModel.GTXFromDate.Date)
&& (DbFunctions.TruncateTime(x.CreatedDate.Value) <= viewModel.GTXToDate.Date));

As a rule, you should store dates and times in UTC in your database.
Convert any local date/times to UTC in your code before you store them in the database.
Similarly, if you need to show local time from the UTC in the database, then convert it in code after the database fetch.

Convert DateTime to String for comparison, for example:
const string DATE_FORMAT = "yyyy/MM/dd";
var query = sampleTable.Where(x => x.DateTime.ToString(DATE_FORMAT) > DateTime.Now.ToString(DATE_FORMAT));

Found the solution on this question
public partial class Person {
partial void OnLoaded() {
this._BirthDate = DateTime.SpecifyKind(this._BirthDate, DateTimeKind.Utc);
}
}

Related

How to compare the database field and datetime in asp.net

NET and I working on a program where I take some data from database and try to compare with the DateTime field.
For Example I have certain documents in the SEIBEL database and I want expiration date of those documents and compare the with current date and time and fire message accordingly. But somehow I an unable to compare them.
This is the sql query in asp.net that I am running
private static readonly string GET_PROVIDER_DOCUMENTS = #"
select sc.row_id,
doc.created as created_date,
doc.attrib_04 as document_type,
doc.attrib_47 as exipration_date,
att.row_id as document_row_id,
att.file_name || '.' || att.file_ext as file_name
from siebel.s_org_ext sc
join siebel.s_org_ext_xm doc
on doc.par_row_id = sc.row_id
and doc.type = 'SCLicenseInfo'
and doc.attrib_35 = 'Expiration Date'
and doc.attrib_04 in ('Certificate of Insurance', 'Master Service Agreement')
left join siebel.s_accnt_att att on att.comments = doc.row_id
where sc.row_id = :sc_row_id
";
and this where I trying to get expiration date from database
ExpirationDate = ConvertExpirationDate(dr["exipration_date"].ToString()),
If anybody has any idea about it it would great. Thanks in advance
Have you looked at the TryParse method on a DateTime object?
https://msdn.microsoft.com/en-us/library/system.datetime.tryparse(v=vs.110).aspx
May be suitable for your needs though I believe it will depend on the format your date is stored in.
Assuming you are successfully getting the datetime from the datebase and storing it as a string called ExpirationDate:
DateTime date1 = Convert.ToDateTime(ExpirationDate);
Datetime date2 = new Datetime(---)//desired date to compare with.
if(DateTime.Compare(date1,date2)==0)
{
// They're equal.
}
else
{
// Not equal.
}
Converting:
https://msdn.microsoft.com/en-us/library/system.convert.todatetime(v=vs.110).aspx
Comparing:
https://msdn.microsoft.com/en-us/library/system.datetime.compare(v=vs.110).aspx
Alternatively you could compare the day / month / year components of the date like this :
DateTime today = DateTime.Today;
if(ExpirationDate.Year == today.Year &&
ExpirationDate.Month = today.Month && ExpirationDate.Day = today.Day )

Operator >= cannot be applied to operands of type string and datetime

The user enters two parameters in the url which are the start date and end date and they are entered in the format yyyyMMddhhmm as a string. I'm attempting to take these strings and turn them into dates so I can query my database.
[ResponseType(typeof(Detail))]
public IHttpActionResult GetDetail(string StartDate, string EndDate)
{
DateTime StartDateTime;
DateTime EndDateTime;
StartDateTime = new DateTime();
EndDateTime = new DateTime();
StartDateTime = DateTime.ParseExact(StartDate, "yyyyMMddhhmm", null);
EndDateTime = DateTime.ParseExact(EndDate, "yyyyMMddhhmm", null);
var detail = from a in db.Details where (a.callDate >= StartDateTime && a.callDate <= EndDateTime) select a;
var Response = new DetailResponse() { status = true, calls = detail };
return Ok(response);
}
However I get the error that >= can't be used in datetime and strings.
EDIT:
For the sake of one of the answer I'm including a model class I'm using to display the data.
DetailResponse.cs
public class DetailResponse
{
public bool status { get; set; }
public string statusMessage { get; set; }
public IQueryable<Detail> calls { get; set; }
}
Probably this is happening, because callDate is a string. So you can't compare a string with a datetime. The solution to this problem is to have the same type. That being said I would convert a.callDate to a DateTime.
However, I think that it would be better you change the data type of callDate in the database level. Undoubtedly, this is a personal opinion. So you don't have to follow it. Doing so your code will not need any change.
Now, in terms of code the solution I suggested above is the following:
var allDetails = db.Details.AsEnumerable();
var details = from detail in details
let callDate = DateTime.ParseExact(detail.callDate, "yyyyMMddhhmm", null)
where callDate >= StartDateTime
&& callDate <= EndDateTime
select detail;
Update
As we concluded in comments, we had to call the AsEnumerable, in order the above query to work. Why is this needed?
Borrowing Jon Skeet's words from Reimplementing Linq to Objects: Part 36 – AsEnumerable
Now it’s not entirely uncommon to want to perform some aspects of the
query in the database, and then a bit more manipulation in .NET –
particularly if there are aspects you basically can’t implement in
LINQ to SQL (or whatever provider you’re using). For example, you may
want to build a particular in-memory representation which isn’t really
amenable to the provider’s model.
The DateTime.ParseExact cannot be translated properly in a database method.
Your comparison is failing because the date in your database is of type string, try doing like this:
[ResponseType(typeof(Detail))]
public IHttpActionResult GetDetail(string StartDate, string EndDate)
{
DateTime StartDateTime = DateTime.ParseExact(StartDate, "yyyyMMddhhmm", null);
DateTime EndDateTime = DateTime.ParseExact(EndDate, "yyyyMMddhhmm", null);
var detail = from a in db.Details where (DateTime.ParseExact(a.callDate, "yyyyMMddhhmm", null) >= StartDateTime &&
DateTime.ParseExact(a.callDate, "yyyyMMddhhmm", null) <= EndDateTime) select a;
}
However you are probably best off chaning the type of your callDate to a date instead of a string.
What does your schema look like? is callDate a string? you may need to convert callDate to a DateTime before you can do the comparison.
var detail = from a in db.Details where (Convert.ToDateTime(a.callDate) >= StartDateTime && Convert.ToDateTime(a.callDate) <= EndDateTime) select a;
As has already been said, you can't compare a string to a DateTime, however, given that the date format is
yyyyMMddhhmm
(ie. year month day hour minute) where the values are all numeric and go from least varying -> most varying you will be safe doing a string comparison:
var detail = from a in db.Details where (a.callDate >= StartDate && a.callDate <= EndDate) select a;
This is because "201601010101" is less than "201612312359" when comparing strings (in the same way that "a" is less than "b").
This will save you converting the data to DateTime.
Having said that, by doing the conversion you are validating the data and can show an error if it's not in the right format.

Array find all dates before current date

Hello I am currently trying to array.find all the dates before the current date. I have tried both using the datetime.now as well as creating a seperate variable for current date in my struct but i keep getting "Cannot implicitly convert type 'Assignment_3.Program.Hire' to 'System.DateTime". I'm sure the solution is quite simple but as a novice it does escape from me. If you need any more of the code I will be happy to provide
struct Hire
{
public int CustomerNo;
public int DVDNo;
public DateTime HireDate;
public int NoNights;
public DateTime CurrentDate = DateTime.Now;
}
DateTime result = Array.Find(hiredetails, Hire => Hire.HireDate <= Hire.CurrentDate);
Array.Find<T> returns the element matching the criteria. In you case since it is an array of Hire type, it will return element of type Hire, which you cannot assign to DateTime. You can do:
List<DateTime> allDates = hiredetails.Where(hire=> hire.HireDate <= hire.CurrentDate)
.Select(r=> r.HireDate)
.ToList();
You can also return IEnumerable<DateTime> and exclude ToList() from the above statement.
Not really sure if you need this but instead of keeping the current date inside the object you can have that in your local variable and pass that in your query like:
DateTime currentDate = DateTime.Now;
List<DateTime> allDates = hiredetails.Where(hire=> hire.HireDate <= currentDate)
.Select(r=> r.HireDate)
.ToList();
Do not store current date in a structure, use local variable instead, solution would look like:
var currentDate = DateTime.Now;
var result = hiredetails.Select(h => h.HireDate).Where(d => d <= currentDate);

How to get DateTime with a UTC datetime and a particular timezone?

My data in SQL database looks like this:
PubDateUTC PubDateUTCOffset
----------------------- --------------------
2011-08-04 10:02:50.000 +8:00:00
2012-04-23 02:32:25.287 +8:00:00
2010-09-26 04:23:00.000 +8:00:00
What I want is to get a DateTime based on PubDateUTC and PubDateUTCOffset, for example:
2011-08-04 10:02:50.000, +8:00:00 should result in 2011-08-04 18:02:50:000
I have tried with TimeZoneInfo class, but I don't know hot to create a instance of TimeZoneInfo with a string like "+8:00:00", which would be the CreateTimeZoneInfo method below
var tz = CreateTimeZoneInfo(post.PubDateUTCOffset);
return TimeZoneInfo.ConvertTimeFromUtc(post.PubDateUTC, tz);
Is there anyway to do this?
Note: I cannot change the data in SQL database.
You could try something like:
var date = post.PubDateUTC.Add(
TimeSpan.Parse(post.PubDateUTCOffset.Replace("+", ""))
);
The .Replace("+", "") is because TimeSpan will handle -01:00:00 but will choke on +01:00:00
I think you need to use DateTimeOffset class. This thread may be helpful.
http://msdn.microsoft.com/en-us/library/bb546101.aspx
This works, remove any leading "+" from the offset ( "-" are ok)
var d = new DateTimeOffset(DateTime.Parse("2011-08-04 10:02:50.000"),
TimeSpan.Parse("08:00:00"));
d.DateTime - the time in db = 10:02:50
d.LocalDateTime - the time according to your servers timezone
d.UtcDateTime - the time at GMT = 02:02:50
I'm not sure you want 18:02:50 since it is the time at GMT+16 (+16:00:00), unless of course that is how it's encoded in the db, then just ignore this post :)
You should change your post class to have one property:
public DateTimeOffset Published { get; set; }
Then when you read from the database (assuming you have datetime and varchar types in your database):
DateTime utc = DateTime.SpecifyKind(
(DateTime) reader["PubDateUTC"], DateTimeKind.Utc);
TimeSpan offset = TimeSpan.Parse(
((string) reader["PubDateUTCOffset"]).Replace("+", ""))
post.Published = new DateTimeOffset(utc).ToOffset(offset);
Then when you need to consume it, you have all of the options of a full DateTimeOffset:
DateTime local = post.Published.DateTime; // with your offset applied
DateTime utc = post.Published.UtcDateTime; // the original utc value
string s = post.Published.ToString("o"); // 2011-08-04T18:02:50.0000000+08:00

C# MySQL LINQ DateTime conversion

I'm trying to retrieve records from a mySQL DB using LINQ and C#.
The date in c# code is a string: 23-01-2010
I need to convert this to DateTime format as 2010-01-23 (mySQL default DateTime format), otherwise the query does not return any records, at present it errors saying a string cannot be matched against a DateTime (row.DateOfIssue)
If I convert the string to DateTime (C#), then it is not in the mySQL DateTime format of yyyy-MM-dd
String endDate = "23-01-2010";
var query = (from row in uow.UserPersonalLicenseDetails
where (endDate >= row.DateOfIssue && endDate <= row.DateOfExpiry)
select row)
This is such a standard query it seems mad that it is so hard to do in LINQ.
It seems putting any method like CompareTo etc in the where clause causes an error of "Search for a class that works in this scenario"
I'm now wondering if the best line of attack might be to write a stored procedure in the database. This could then take the C# datetime as a parameter, convert it to mySQL format and then run the required query.....
Any thoughts?
Make it a DateTime - so
var myDate = DateTime.Parse(endDate);
Then
myDate.ToString("yyyy-MM-dd");
---------- or this:
var myDate = DateTime.Parse(endDate);
var query = (from row in uow.UserPersonalLicenseDetails
where ((myDate.CompareTo(row.DateOfIssue)>=0 && (myDate.CompareTo(row.DateOfExpiry)<=0)
select row
Just convert your date string to DateTime and then in the LINQ convert the string to DateTime that's coming back in order to do the comparison. I've used ParseExact because we need to make sure that we are parsing to the exact format that MySQL stores the date in, which is yyyy-MM-dd hh:mm.
Something like:
var endDate = DateTime.Parse("23-10-2010").ToString("yyyy-MM-dd hh:mm");
var formattedEndDate = DateTime.Parse(endDate);
//you could cut that to one line by putting the date in said format in the first place
var query = (from row in uow.UserPersonalLicenseDetails
where formattedEndDate >= row.DateOfIssue
&& formattedEndDate <= row.DateOfExpiry
select row)
Ok, problem was that the Table had the field defined as DATE rather than DATETIME so no match was being made.
Used DateTime.Date and the match was made.

Categories