DateTime ParseExact gives System.FormatException: - c#

I am getting the following error:
System.FormatException: 'String '{ ActualInstallDate = 17/04/2020 09:06:23 }' was not recognised as a valid DateTime.
I have to add that in the database ActualInstallDate is nullable, that's why I'm converting it to string, to 'trick' it. The error comes at parsing actualInstallDates. Not sure what's wrong here.
Any suggestion is highly appreciated.
var actualInstallDates = _context.Units.Where(u => u.ID == unitID)
.Select(u => new {
u.ActualInstallDate
}).Single().ToString();
if (actualInstallDates != null)
{
DateTime actualInstallDate = DateTime.ParseExact(actualInstallDates, "dd/MM/yyyy", CultureInfo.InvariantCulture);
var nowString = DateTime.Now.ToString("dd/MM/yyyy");
DateTime now = DateTime.ParseExact(nowString, "dd/MM/yyyy", CultureInfo.InvariantCulture);
var averageWorkOver = (Math.Ceiling(Math.Ceiling(Convert.ToDecimal(now - actualInstallDate)) / 1000 * 60 * 60 * 24) / workOverList.Count).ToString();
ViewBag.AverageWorkOver = averageWorkOver;
}
[Column(TypeName = "datetime2")]
[Display(Name = "ActualInstallDate", Description = "ActualInstallDate_Description", ResourceType = typeof(Resource.Models.Unit))]
public DateTime? ActualInstallDate { get; set; }

You did'nt specify time in the format string. You can either truncate the time part from the date string or add time to the format string.
something like this:
DateTime actualInstallDate = DateTime.ParseExact(actualInstallDates, "dd/MM/yyyy HH:mm:ss", CultureInfo.InvariantCulture);

First of all you don't need to select it into anonymous object (if ActualInstallDate is string in database):
var actualInstallDates = _context.Units
.Where(u => u.ID == unitID)
.Select(u => u.ActualInstallDate)
.SingleOrDefault();
if (actualInstallDates != null)
{...}
If you still want to, the don't call ToString on it:
var actualInstallDates = _context.Units.Where(u => u.ID == unitID)
.Select(u => new { u.ActualInstallDate })
.Single();
if (actualInstallDates.ActualInstallDate != null)
{
DateTime.ParseExact(actualInstallDates.ActualInstallDate ...)
...
}
Secondary your date format does not match with the string, try using
DateTime.ParseExact(actualInstallDates, "dd/MM/yyyy hh:mm:ss", CultureInfo.InvariantCulture)
UPD
Since your field is DateTime? it seems that you've been missing Value property on Nullable<> struct so you just need to fetch your date from db and use actualInstallDates.Value:
var actualInstallDates = _context.Units
.Where(u => u.ID == unitID)
.Select(u => u.ActualInstallDate)
.Single()
if (actualInstallDates != null)
{
var averageWorkOver = (Math.Ceiling(Math.Ceiling(Convert.ToDecimal(DateTime.Now - actualInstallDates.Value)) / 1000 * 60 * 60 * 24) / workOverList.Count).ToString();
ViewBag.AverageWorkOver = averageWorkOver;
}

Related

Converting an SQL with Left Join , Group and Sum to a Linq Query

I am trying to replicate the below SQL in C# & Linq , but I am not too experienced with Linq beyond the basics.
SELECT SUM(coalesce(cd.minutesspent,0))
FROM timelabels t
LEFT JOIN challengedetails cd on cd.createddate = t.date
GROUP BY t.date
This would give me a sum of minutes for every date, or zero if there were null entries. Pretty straightforward I think.
// timelabels structure
DateTime start = DateTime.Now.AddDays(-14);
DateTime end = DateTime.Now;
List<DateTime> timelabels = new List<DateTime>();
for (var dt = start; dt <= end; dt = dt.AddDays(1))
{
timelabels.Add(dt);
}
// ChallengeDetails structure & sample data
class ChallengeDetails(){
DateTime? Createddate
int? MinutesSpent
}
List<ChallengeDetails> ChallengeDetails = new List<ChallengeDetails >();
List<ChallengeDetails> ChallengeDetails = new List<ChallengeDetails>();
ChallengeDetails.Add(new ChallengeDetails { MinutesSpent = 44, Createddate = DateTime.Now.AddDays(-10) });
ChallengeDetails.Add(new ChallengeDetails { MinutesSpent = 31, Createddate = DateTime.Now.AddDays(-7) });
ChallengeDetails.Add(new ChallengeDetails { MinutesSpent = 13, Createddate = DateTime.Now.AddDays(-3) });
ChallengeDetails.Add(new ChallengeDetails { MinutesSpent = 77, Createddate = DateTime.Now.AddDays(-2) });
// The Actual Code
List<string> timedata = (from a in timelabels
join al in ChallengeDetails on a equals al.Createddate into All
from al in All.DefaultIfEmpty()
group al by a into grouped
select grouped.Sum(m => m.MinutesSpent ?? 0).ToString()
).ToList();
Looking at this it should work - I have DefaultIfEmpty which should replicate the left join. Within the Sum I have '?? 0' which should be the fallback for any dates that dont have a ChallengeDetail.
But I get System.NullReferenceException: 'Object reference not set to an instance of an object.'
m was null. I shouldnt have gotten this as I have null entries covered or have I got this all wrong ?
Under the section "Actual Code" just add a parenthesis in Sum function, as below
It should take care of null , even before Sum works.
select grouped.Sum(m => (m.MinutesSpent ?? 0)).ToString()
This will do for you, using LINQ - Lambda Expressions:
var TotalMinutesSpentGroupedList = timelabels
.GroupJoin(challengedetails,
t => date,
cd => createddate,
(t,cd) => new
{
MinutesSpent = cd.minutesspent ?? 0,
CreateDate = cd.createddate ?? DateTime.Now
})
.SelectMany(tcd=> challengedetails.DefaultIfEmpty(),
(t, cd) => new
{
MinutesSpent = cd.minutesspent ?? 0,
CreateDate = cd.createddate ?? DateTime.Now
})
.Select(s => new
{
MinutesSpent = cd.minutesspent ?? 0,
CreateDate = cd.createddate ?? DateTime.Now
})
.GroupBy(g => g.createddate).Select(item => item.Sum(s => s.minutesspent));

how to assign custom time to a string when converting it to dateTime in c#

I get a string as "Start:6/23/2020 End:7/31/2020" and for converting it into specific datetime format I have written the following code where I have removed the Start: and End: and while converting I want to assign the time as 11:59:59 PM to end the end date. How can we do it?
if (s.FilterBy.Equals("Submit Date"))
{
s.SearchTerm = s.SearchTerm.Replace("Start:", "").Replace("End:", "");
string[] date = s.SearchTerm.Split(' ');
DateTime startDate = Convert.ToDateTime(date[0]);
DateTime endDate = Convert.ToDateTime(date[1]);
var idList = accessBrokerService.GetFileteredIds(s.SearchTerm);
// StringComparison comp = StringComparison.OrdinalIgnoreCase;
requestListItems = requestListItems.Where(x => string.IsNullOrEmpty(s.SearchTerm)
|| (x.RequestDate >= startDate && x.RequestDate <= endDate)
|| idList.Any(list => list.Equals(x.RequestItemKey))).ToList();
}
So it was suggested the comments I tried out adding endDate = endDate.AddDays(1).AddSeconds(-1); and it worked.
And this is how my code looks like now
if (s.FilterBy.Equals("Submit Date"))
{
s.SearchTerm = s.SearchTerm.Replace("Start:", "").Replace("End:", "");
string[] date = s.SearchTerm.Split(' ');
DateTime startDate = Convert.ToDateTime(date[0]);
DateTime endDate = Convert.ToDateTime(date[1]);
endDate = endDate.AddDays(1).AddSeconds(-1);
var idList = accessBrokerService.GetFileteredIds(s.SearchTerm);
// StringComparison comp = StringComparison.OrdinalIgnoreCase;
requestListItems = requestListItems.Where(x => string.IsNullOrEmpty(s.SearchTerm)
|| (x.RequestDate >= startDate && x.RequestDate <= endDate)
|| idList.Any(list => list.Equals(x.RequestItemKey))).ToList();
}

Entity framework "Select date time from string"

I need to select the records from a table for date interval.
But the date to select from is kept as nvarchar in this pattern
20160511_155015 (yyyymmdd_hhmmss)
I cannot use ToList() to make it as DateTime.ParseExact(entry.StartDate, "yyyyMMdd_HHmmss", CultureInfo.InvariantCulture)
The table keeps several millions records.
So I need to make something like this:
var preQuery = context.Table
.AsNoTracking()
.Select(x => new
{
StartDate = ConvertFrom()),
Mode = x.Mode,
SessionStart = x.AStart,
SessionEnd = x.AEnd,
x.SensorNumber
})
.Where(x => x.StartDate != null
&& x.StartDate >= startDate
&& x.StartDate <= endDate)
.ToList();
Is it possible to convert the string representation to Datetime and then proceed with Where clause ?
Please try this DateTime.ParseExact(dateTime ,format,CultureInfo.InvariantCulture);
var preQuery = context.Table.AsNoTracking().Select(x => new
{
StartDate = ConvertFrom(),
Mode = x.Mode,
SessionStart = DateTime.ParseExact(x.AStart,"yyyyMMdd_HHmmss", CultureInfo.InvariantCulture),
SessionEnd = DateTime.ParseExact(x.AEnd,"yyyyMMdd_HHmmss", CultureInfo.InvariantCulture),
x.SensorNumber
})
.Where(x => x.StartDate != null && x.StartDate >= startDate && x.StartDate <= endDate)
.ToList();
You can try:
StartDate.StartsWith("20160511") or so..
or
Convert.ToInt32(StartDate.Substring(0,8)) > 20160511
by the way, i think you might want to run a script, as long as it takes, and create a new column which will generate a DateTime based on that column

Time of DateTime C# MVC

I am trying to compare 24 hour time format stored as a string to the current time as follows
[AllowAnonymous]
public ActionResult _ProgOn()
{
int i = (int)DateTime.Now.DayOfWeek;
DateTime dt = DateTime.Now;
var onNow = db.Programs
.Where(u => u.PrOk == true)
.Where(u => u.DaId == i)
.Where(u => u.TimeOn == dt.ToString("HH:mm"));
return PartialView(onNow);
But that seems not to be acceptable to Linq query. I will be grateful if I am pointed to the right direction.
Pass time string to Linq query:
int i = (int)DateTime.Now.DayOfWeek;
string time = DateTime.Now.ToString("HH:mm");
var onNow = from u in db.Programs
where u.PrOk &&
u.DaId == i &&
u.TimeOn == time
select u;
return PartialView(onNow);
Also you don't need to compare boolean value with true/false. And I think query syntax looks better here.
Linq will only be able to use what it can translate. Try doing the conversion of the DateTime to a string and then do the comparison:
[AllowAnonymous]
public ActionResult _ProgOn()
{
string t = dt.ToString("HH:mm");
int i = (int)DateTime.Now.DayOfWeek;
DateTime dt = DateTime.Now;
var onNow = db.Programs
.Where(u => u.PrOk == true)
.Where(u => u.DaId == i)
.Where(u => u.TimeOn == t);
return PartialView(onNow);

DateTime comparison without time part?

I wrote this code. But I want to ignore time, I want to compare only day.
from s in sayac_okumalari
where s.okuma_tarihi == startDate && s.sayac_id == sayac_id
group s by new { date = new DateTime(((DateTime)s.okuma_tarihi).Year, ((DateTime)s.okuma_tarihi).Month, ((DateTime)s.okuma_tarihi).Day, ((DateTime)s.okuma_tarihi).Hour, 1, 1) } into g
select new
{
okuma_tarihi = g.Key.date,
T1 = g.Sum(x => x.toplam_kullanim_T1),
T2 = g.Sum(x => x.toplam_kullanim_T2),
T3 = g.Sum(x => x.toplam_kullanim_T3)
};
for example:
25.02.1987 == 25.02.1987
use s.okuma_tarihi.Value.Date == startDate.Date. This should allow you to compare only the Date component.
Update From the discussion in comments looks like the user is using NullableType. Hence updated the solution for NullableType.
Use Date property of DateTime. For ex,
var date= DateTime.Now.Date;
Because you could convert s.okuma_tarihi to DateTime, I think you could do:
var sonuc = from s in sayac_okumalari
where (DateTime)s.okuma_tarihi.Date == startDate.Date && s.sayac_id == sayac_id
group s by new { date = new DateTime(((DateTime)s.okuma_tarihi).Year, ((DateTime)s.okuma_tarihi).Month, ((DateTime)s.okuma_tarihi).Day, ((DateTime)s.okuma_tarihi).Hour, 1, 1) } into g
select new
{
okuma_tarihi = g.Key.date,
T1 = g.Sum(x => x.toplam_kullanim_T1),
T2 = g.Sum(x => x.toplam_kullanim_T2),
T3 = g.Sum(x => x.toplam_kullanim_T3)
};
Hope it helps.
Try using the Date property on the DateTime Object will be a good a simple solution.
string AdmissionDate = "10/15/2017" // mm/dd/yyyy
string DepartureDate = "10/14/2017" // mm/dd/yyyy
if (Convert.ToDateTime(AdmissionDate).Date > Convert.ToDateTime(DepartureDate).Date)
{
// Validation: Admission Date can not be greater than Departure Date...
}
Try this...
try
{
DateTime Date1= DateTime.ParseExact(txtBox1.Text,"dd/MM/yyyy",null);
DateTime Date2 = DateTime.ParseExact(txtBox2.Text, "dd/MM/yyyy", null);
if (Date1 > Date2)
{
//........
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

Categories