I have a table with a couple of columns called Key and Value.
One of the Keys is called RequestedOn and the value is a timestamp saved as a string.
Now in my linq query I would like to compare this timestamp, for example
var startDate = DateTime.Now.AddDays(-7);
var endDate = DateTime.Now;
var query = (from ep in db.ExtendedProperties
where
ep.Key == "RequestedOn" && ep.Value >= startDate && ep.Value <= endDate
select ep).ToList();
Now I know I cannot compare ep.Value (string) against startDate or endDate, and I cannot convert ep.Value to a DateTime as it couldn't make sense. Any ideas on a solution?
Thanks in advance?
if its saved as string you must parse it to DateTime and then compare
You can either:
Convert the DateTime to string
Convert the string to DateTime
Write a method that compares the 2 directly
Something else
Using LINQ for something that does not have a type and contains different data is not a good option. The whole point of LINQ is to have types.
That being said one solution to your problem is to save the date in a format that is comparable as string such as 201405231801 (being 23.05.2014 18:01) and just compare strings.
Of course you care about timezones and daylight saving time you are guaranteed to get it wrong.
If you save your strings right you can actually do a comparison:
For example: '20131201125959': year, month, date, hours, minutes, seconds.
Related
I have a list of data that have datetimeoffset? as a column inside. I want to get specific data that has the month I want but don't know how. Below are those code I have tried.
This return me with error of No overload for method 'Tostring' which is weird since I can pass datetimeoffset? and use it in other function but if I do it directly inside where I get it, I can't use it.
int d = DateTime.Now.Month;
string f = d.ToString();
var s = _dbContext.Documents.FirstOrDefault(x => x.ApplyDate.ToString("MM") == f);
return Json(s);
This return null
int d = DateTime.Now.Month;
string f = d.ToString();
var s = _dbContext.Documents.FirstOrDefault(x => x.ApplyDate.Value.ToString("MM") == f);
return Json(s);
You can retrieve the month of a nullable datetimeoffset like this:
DateTimeOffset? dt;
dt?.Value.Month;
However, I really wonder if EF will be able to translate this:
x => x.ApplyDate?.Month == f
into a SQL expression. I presume that it will fallback to in-memory filtering.
Next to that, even if EF is able to translate this into a SQL expression, it won't be optimal as indexes that might be defined on that column will not be used.
Therefore, I'd suggest to rewrite your LINQ expression to something like this:
x :> x.ApplyDate != null && x.ApplyDate >= new DateTimeOffset(someDate.Year, someDate.Month, 1) && x.ApplyDate <= new DateTimeOffset(someDate.Year, someDate.Month, daysInMonth)
(Given you want to retrieve the data that belong to a specific month in a specific year. If you want to retrieve records that belong to a certain month, regardless the year, I see no other option)
DateTimeOffset? is Nullable type therefore is has no overload of ToString(string format) like DateTimeOffset has.
to get get the month value from your DateTimeOffset? you can
x.ApplyDate.Value.ToString("MM")
x.ApplyDate.Value.Month
please consider that you might want to check if ApplyDate.Value is null before obtaining its Month property
Your code above shows DateTime, not DateTimeOffSet.
DateTimeOffSet is Struct, and if you have a nullable value, you need to check the value first and then get the month from the value part
DateTimeOffSet myNullableDateTime = someValue...//
Option 1:
// notice I added value below
myNullableDateTime.HasValue? "?Month="+myNullableDateTime.EscapeDataString(myNullableDateTime.Value.ToString()):"")
Option 2:
if(myNullableDateTime.HasValue)
{
var Month = myNullableDateTime.Month
TimeSpan difference = DateTimeOffset.Now.Subtract(myNullableDateTime.Value);
// convert the difference to what you need and get Month
}
I have not compiled it, but it should get you the answer or pretty close.
I have a date value that I want to strip the time from. I want the return type to be a date type since I want to order the list of date I have. having a list to string representing Date does not return a correct order.
I know that DateTime always returns the date with the time. What are my options here? How can I better my code and have a list of items of Date type without the time?
Edit: I would like to have the date only. nothing after that. Something like 8/7/2016 not 8/7/2016 00:00:00 or anything after date. and in a date object.
Here is my code:
using (var db = new MyModel.Context())
{
var cert = (
from tr in db.uspTranscripts(personId)
from a in db.PersonTranscripts.Where(x => x.UPID == personId)
from b in db.LU_CreditType.Where(x => x.ID == a.CreditTypeID)
select new CertViewModel
{
ActivityTitle = tr.ActivityTitle,
Score = tr.Score,
Status = tr.Status,
CompletionDate = tr.CompletionDate,
CretitTypeName = b.ShortName,
CompletedDateSorted = a.HK_CreatedOn
}).OrderByDescending(x => x.CompletedDateSorted).ToList();
List<CertViewModel> certlist = cert;
foreach (var item in certlist)
{
string itemWithoutHour = item.CompletionDate.Value.ToShortDateString();
var itemConverted = DateTime.ParseExact(itemWithoutHour, "M/d/yyyy", null);
item.CompletionDate = itemConverted;
}
return certificateslist.GroupBy(x => x.ActivityTitle).Select(e => e.First()).ToList();
}
For any given DateTime object, you can reference its Date property to strip out the time values:
var withTime = DateTime.Now; // 8/7/2016 22:11:43
var withoutTime = withTime.Date; // 8/7/2016 00:00:00
The .NET framework does not have a date-only object.
It may be worth understanding how the DateTime structure works. Internally, it stores an offset in ticks (1 tick = 100 nanoseconds) since 1/01/0001 12:00 am in a single 64-bit unsigned integer. (1 tick = 100 nanoseconds)
The DateTime structure then provides many useful methods and properties for dealing with dates and times, such as adding some days to an existing date, or calculating the difference of two times. One useful property is Date, which rounds a DateTime object down to the nearest day (12:00 am).
Dates, times and dates-with-times are all very similar, the main difference is how you format them, a date-with-time where you omit the time is just a date.
What David has suggested is that you work with the DateTime structure internally, strip any times using the Date property, sort on the DateTime, compare them and modify them as DateTime objects.
Only convert them to a string when they need to be displayed, at which point you can use methods such as ToShortDateString() or ToString(string format) to display only the date.
I have product list and every product has create date in DateTime type. I want to take some products that created after my entering time in string type.
I enter EnteredDate in string type, like this format : 05/16/2012
1. var dates = from d in Products
2. where d.CreateDate >= DateTime.ParseExact( EnteredDate, "mm/dd/yy", null )
3. select d;
In second line I got error as String was not recognized as a valid DateTime for "mm/dd/yy".
I also tried DateTime.Parse(), Convert.ToDateTime() and got same error.
How can I filter this product list by create date?
"mm" is minutes, and your year is 4 digits, not 2. You want "MM/dd/yyyy", if your format is really always that. How confident are you on that front? (In particular, if it's entered by a user, you should probably make your code culture-sensitive...)
I would suggest pulling the parsing part out of the query though, and also probably using the invariant culture for parsing if you've really got a fixed format:
DateTime date = DateTime.ParseExact(EnteredDate, "MM/dd/yyyy",
CultureInfo.InvariantCulture);
var dates = Products.Where(d => d.CreateDate >= date);
Call
DateTime.ParseExact(EnteredDate, "MM/dd/yyyy", CultureInfo.InvariantCulture);
I have date in this format "1999-05-31T13:20:00.000-05:00" I want to add some hours or days to it . Can some one suggest how to do that with this format and AddDays or AddHours ? Result need to return same format.
Try using DateTimeOffset.Parse. Then use AddDays or AddHours.
It is important to use DateTimeOffset instead of DateTime if you want to preserve the same timezone offset that you parsed.
var dateTimeOffset = DateTimeOffset.Parse("1999-05-31T13:20:00.000-05:00");
var newDateTimeOffset = dateTimeOffset.AddHours(1);
var newDateTimeString = newDateTimeOffset.ToString("O");
if you don't like the way "O" formats, you can use this:
var newDateTimeString = newDateTimeOffset.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK")
This will 100% match to your format.
Example:
txt_del.Text = Calendar1.SelectedDate.ToString("MM/dd/yyyy");
/* for date picking textbox*/
double d2 = double.Parse(txt_till.Text);
/*second textbox for number of days to add*/
DateTime tom = Calendar1.SelectedDate.AddDays(d2);
/*for adding number of days to selected date*/
txt_total.Text = tom.ToString("MM/dd/yy")
Use DateTime.Parse(...) to create a DateTime object. Then you can add days and/or hours, and then ToString() to get the new string.
That looks like datetimeoffset. Perhaps from sql server? You should be able to use the datetimeoffset structure and the parse method. Once you have a datetimeoffset type you can use addhours or related methods.
I have two fields:
string date1 = "04/26/10";
string date2 = "04/25/10";
How can I compare these two fields like so?:
if (date2 <= date1)
{
// perform some code here
}
Can this be done without first converting the fields to a separate date-type variable?
EDIT: I should mention that these values are coming from a database table where the date values are in a string format to begin with. Old legacy code...
No, but it is not difficult to convert to a date in C#.
if ( DateTime.Parse(date2,CultureInfo.InvariantCulture) <= DateTime.Parse(date1,CultureInfo.InvariantCulture))
{
// perform some code here
}
CultureInfo depends on the format the string dates have in the legacy DB. See: DateTime formats used in InvariantCulture
If your dates are actually stored as strings in the database, it seems like you can't be sure they'll be in a valid format before parsing. For that reason I'd suggest a small variation on jle's answer:
DateTime d1, d2;
if (DateTime.TryParse(date1, out d1) &&
DateTime.TryParse(date2, out d2) &&
d2 <= d1)
{
// perform some code here
}
else
{
// strings didn't parse, but hey,
//at least you didn't throw an exception!
}
At the very least you need to pick apart the strings in order to compare them in the right order.
If you want to leave them as strings, then you need to reorder them with LARGEST->SMALLEST units, so this:
yyyy/mm/dd
can be compared directly, but not the format you have. With your format, you need to split it, and either recombine it like above, or compare the individual pieces in the right order.
Having said that, it is rather easy to convert the strings to DateTime using DateTime.ParseExact.
Generally it is a bad idea to compare date as strings.
But if your strings are in the same format (e.g. yyyy/mm/dd means years, then monthes then days) then the comparison may be valid.
It could be done with string manipulation, but it would come down to effectively comparing three sets of integers, which as strings would induce more overhead than converting to datetimes. Why would you want to do that?
No. Let the .net framework sort that out for you. It will correctly identify the user date settings and format (using system settings, current thread) and determine which is the month, year and day - especially if that data comes from eg a sql server.
It's preferred to have the date formatted before doing the comparison. Depending in your cultureinfo, the safest way to compare dates is to format the date string to "yyyy-mm-dd".
DateTime d1, d2;
string date1 = "04/26/10";
string date2 = "04/25/10";
d1 = DateTime.Parse(date1.ToString("yyyy-MM-dd"));
d2 = DateTime.Parse(date2.ToString("yyyy-MM-dd"));
if (d1 > d2)
{
//do something
}
Best practice is to avoid comparing date as string types and compare with the official DateTime object of C#.
If your use-case requires the comparison using string objects then:
1st, make sure the date string format is yyyymmdd as recommend by Lasse V. Karlsen.
2nd, use the string method CompareTo to compare between the dates.
Here's how the method works in your case (Used C# Online Compiler to test this):
using System;
public class Program
{
public static void Main()
{
string fmt = "yyyymmdd";
string min = "20201206";
string max = "20210810";
Console.WriteLine(max.CompareTo(min)); // Output : 1
Console.WriteLine(min.CompareTo(max)); // Output : -1
string same1 = "20001212";
string same2 = "20001212";
Console.WriteLine(same1.CompareTo(same2)); // Output : 0
Console.WriteLine(same2.CompareTo(same1)); // Output : 0
// Summary:
// 1 = Greater than string param
// -1 = lesser than string param
// 0 = equals to string param
}
}