String '22-05-1998' was not recognized as a valid DateTime - c#

I am using CsvHelper library to read the data from a CSV file looks like
this
My code:
public class CsvTransaction
{
[Name("Account")]
public string Account { get; set; }
[Name("Amount")]
public int Amount { get; set; }
[Name("Date")]
public DateTime Date { get; set; }
[Name("Note")]
public string Note { get; set; }
}
public void call()
{
using (var StreamReader = new StreamReader(#"C:\Users\santo\Downloads\industry.csv"))
{
using (var csvReader = new CsvReader(StreamReader, CultureInfo.InvariantCulture))
{
var records = csvReader.GetRecords<CsvTransaction>().ToList();
Console.WriteLine(records.Count);
foreach(var item in records)
{
Console.WriteLine(item.Amount.GetType());
Console.WriteLine(item.Note.GetType());
CsvAddTransaction(item.Account, item.Amount, item.Date, item.Note);
}
}
}
}
when I call this call(), it is saying String '22-05-1998' was not recognized as a valid DateTime. all the other are giving exact datatypes I needed, but there is a problem with item.Date
Can anyone help me with this?

You have to define DateTime format, you are getting this error because parsing mechanism might be expecting something like "MM-dd-yyyy" and instead of that, it receives "dd-MM-yyyy".
Here's documentation which describes DateTime formatting in detail.
And here is url to potential solution to your problem.

Related

Serializing class to .json file

just trying to do a simple serialize(first time trying).
actually had this working up until I changed a few things and added a deserialize and added a class that made my other way no longer work.
basically I took what I had for deserialize json to object and tried to just reverse the order of things. but now I get an error at a foreach loop I'm not sure if I even need.
Once I get the serialize working I'm sure I will also be stuck on how to format the string as it enters the .json file so it appends properly but that is for another day.
here is error i received
System.NullReferenceException: 'Object reference not set to an instance of an object.'
i receive this exception on the line foreach(var translogs in Logs.transLogs)
here is my event.
Code
private void toolPull_Click(object sender, EventArgs e)
{
double cost = Convert.ToDouble(active_Cost.Text);
int serial = Convert.ToInt32(transactionSerial_Box.Text);
DateTime timeNow = DateTime.Now;
TransactionLogs Logs = new TransactionLogs();
foreach(var translogs in Logs.transLogs)
{
translogs.Employee = transactionEmployee_Box.Text;
translogs.Serial = serial;
translogs.Cost = cost;
translogs.Description = active_Description.Text;
translogs.CurrentDate = timeNow;
}
string stringJson = JsonConvert.SerializeObject(Logs);
StreamWriter sw = new StreamWriter(#"C:\transactionlog.json", append: true);
sw.WriteLine(stringJson);
sw.Close();
}
Here is the class to work with json
namespace QuickType
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public partial class TransactionLogs
{
[JsonProperty("TransactionLog")]
public List<TransactionLog> transLogs { get; set; }
}
public partial class TransactionLog
{
[JsonProperty("employee")]
public string Employee { get; set; }
[JsonProperty("currentDate")]
public DateTime CurrentDate { get; set; }
[JsonProperty("serial")]
public int Serial { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("isPull")]
public bool IsPull { get; set; }
[JsonProperty("cost")]
public double Cost { get; set; }
}
}
and here is json file
{
"TransactionLog":[
{
"employee":"Joey",
"currentDate":"2021-11-03T11:49:13.5741628-04:00",
"serial":1111,
"description":"1/2-20 Threadmill",
"isPull":true,
"_ost":25.68
},
{
"employee":"joey",
"currentDate":"2021-11-03T11:50:34.6344474-04:00",
"serial":1000,
"description":"1/2-20 Threadmill",
"isPull":true,
"cost":25.68
},
{
"employee":"john",
"currentDate":"2021-11-03T11:50:40.9956616-04:00",
"serial":2000,
"description":"1/2-20 Threadmill",
"isPull":true,
"cost":25.68
},
{
"employee":"Jim",
"currentDate":"2021-11-03T11:51:24.5559292-04:00",
"serial":4565,
"description":"1/2-20 Threadmill",
"isPull":true,
"cost":25.68
}
]
}
Let me capture here the outcome of the comments.
There were two problems with these two lines:
TransactionLogs Logs = new TransactionLogs();
foreach(var translogs in Logs.transLogs)
The TransactionLogs's transLogs collection is not initialized, that's caused the NRE
After fixing that the foreach went through on an empty collection
The fix for the first problem:
Logs.transLogs = new List<TransactionLog>();
The fix for the second problem:
var transLogs = new TransactionLog()
{
Employee = transactionEmployee_Box.Text;
Serial = serial;
Cost = cost;
Description = active_Description.Text;
CurrentDate = timeNow;
};
Logs.transLogs.Add(transLogs);
So, rather than iterating through the empty collection, you had to populate it by adding a new member.

How to query Entity Framework database for records between 2 dates, then return that information for display on screen

I have an Entity MVC app with a code-first database. I need to produce a search box to search between 2 dates and return the records between those dates.
I will call the method with jQuery/ajax and render the results in a table.
I've tried writing an API, with no success. I am not even sure if this is the correct way to go about it?
namespace Areometrex_Leaflet.Models
{
[Table ("Flight_Lines")]
public class Flight_line
{
[Key]
public string Swath_name { get; set; }
public string Flight_name { get; set; }
public string Swath_record { get; set; }
public string Flight_date { get; set; }
public decimal Start_lat { get; set; }
public decimal Start_long { get; set; }
public decimal End_lat { get; set; }
public decimal End_long { get; set; }
public decimal Altitude { get; set; }
public DateTime Time_start { get; set; }
public DateTime Time_end { get; set; }
public string Sensor { get; set; }
}
public class FlightLineContext : DbContext
{
public DbSet<Flight_line> Flight_Lines { get; set; }
}
}
This is my model that holds the objects in the database. I need to search the "Flight_date" property, that is held in my DB in this following format as an "nvarchar" :
17/11/2018 11:09:18 PM
My current API looks something like this:
[HttpPost]
public IEnumerable<Flight_line> SearchFlight_Line()
{
string start, end;
var rc = RequestContext;
var data = rc.Url.Request.GetQueryNameValuePairs();
{
start = data.FirstOrDefault().Value ?? string.Empty;
end = data.LastOrDefault().Value ?? string.Empty;
}
//db format: 17/11/2018 11:22:56 PM
var s = DateTime.Parse(start);
var flightSearch = new List<Flight_line>();
using (_context)
{
var sql = $"SELECT * FROM Flight_Lines WHERE Flight_Date BETWEEN '{start}' AND '{end}'";
flightSearch = _context.Flight_Lines.SqlQuery(sql).ToList<Flight_line>();
}
return flightSearch;
}
Ideally, I want to call this API with jquery/Ajax and return results to be displayed in an MVC view. My guess is that this is dead easy, but I am only learning and I'm running out of ideas. I would have thought this was really simple, but I am struggling to find the answers I am looking for online, which leads me to believe perhaps I am doing it wrong?
First of all, don't save dates as string in your database, you will just have problems later on.
Instead of:
public string Flight_date { get; set; }
Set it up as DateTime:
public DateTime Flight_date { get; set; }
As far as the query for searching flights go, you can try this. This will return a list of "Flight_line" objects which you can then return wherever you need.
DateTime start = DateTime.Now;
DateTime end = DateTime.Now.AddDays(7);
var flights = _context.Flight_line.Where(f => f.Flight_date >= start && f.Flight_date <= end).ToList();

Sorting a ListBox in c# with multiple fields

Is there a way to sort a list box on one field then another?
(I saw the other posts but I think this is a bit more involved). I could do this the long way but thought there was a faster shorthand version I just wasn't aware of.
Basically this reads a directory for all the folders in it with the format of:
DATENAME
I parse out the name from the date. I need to organize these by name THEN by date (the second filter is what is tripping me up).
So a folder of:
12012016TULLY
1202019LAVA
2202018LAVA
5162019CLOUD
5202020LAVA
would look like
5162019CLOUD
2202018LAVA
1202019LAVA
5202020LAVA
12012016TULLY
So this is what I have:
class MyListBoxItem
{
public string StudyBaseFolder { get; set; }
public string StudyName { get; set; }
public string UserLastName { get; set; }
public string StudyDate { get; set; }
}
List<MyListBoxItem> studiesAndFolders = new List<MyListBoxItem>();
//later int he code i build a list of studyNames (which is a path and I pasre the path here too)
foreach (string sn in studyName)
{
//get user name
String lastName = getLastName(sn);
String theDate = getDate(sn);
//can I organize this based on the LAST NAME THEN THE DATE
studiesAndFolders.Add(new MyListBoxItem { StudyBaseFolder = path, StudyName = sn, UserLastName = lastName, StudyDate = theDate });
}
Then I finally add this to the listbox.
listDirectories.Items.Clear();
//I do it this way so a double click on an item gets the object back and I can do things with it.
foreach(MyListBoxItem direc in studiesAndFolders)
{
listDirectories.Items.Add(direc);
}
listbox.sorted=true didn't help, and I am sure there might be an expression (LINQ to the rescue?). I was just going to do it the long way with a ton of cases when I take the studiesAndFolders and put it to the list.
This code sorts by name, then by date. And should be easy to read.
foreach(MyListBoxItem direc in studiesAndFolders.OrderBy(x => x.StudyName).ThenBy(x => x.StudyDate))
{
listDirectories.Items.Add(direc);
}
As others have noted, you should be storing the StudyDate as a DateTime unless you want it sorted alphabetically.
Firstly, change type of StudyDate to DateTime
class MyListBoxItem
{
...
public DateTime StudyDate { get; set; }
}
After, create new comparer
public class MyListBoxItemComparer : IComparer<MyListBoxItem>
{
public int Compare(MyListBoxItem x, MyListBoxItem y)
{
if (x.StudyName == y.StudyName)
{
return x.StudyDate.CompareTo(y.StudyDate);
}
return String.Compare(x.StudyName, y.StudyName, StringComparison.Ordinal);
}
}
Finally, use SortedSet instead of List
SortedSet<MyListBoxItem> studiesAndFolders = new SortedSet<MyListBoxItem>(new MyListBoxItemComparer());
For ordering based on the date correctly you need StudyDate to be of type DateTime
class MyListBoxItem
{
public string StudyBaseFolder { get; set; }
public string StudyName { get; set; }
public string UserLastName { get; set; }
public DateTime StudyDate { get; set; }
}
Then you can order by using LINQ extension methods.
var orderedDirectories =
directories.OrderBy(dir => dir.StudyName)
.ThenBy(dir => dir.StudyDate);
foreach (var directory in orderedDirectories)
{
listBox.Items.Add(directory);
}
You can override .ToString() method in MyListBoxItem class that listbox will display items as you want.
class MyListBoxItem
{
public string StudyBaseFolder { get; set; }
public string StudyName { get; set; }
public string UserLastName { get; set; }
public DateTime StudyDate { get; set; }
public override string ToString()
{
return $"{StudyDate:MMddyyyy}{StudyName}";
}
}
If you can use LINQ in your project, first you should make StudyDate type of DateTime. Then you could do this:
MyList.OrderBy(x => x.StudyName).ThenByDescending(x=>x.StudyDate).ToList()

How to deserialize JSON date time from MongoDB to C# class

I'm using c# driver to interact with mongoDB.
I have a class that I created and which I populate with the data I get from mongoDB.
One of the properties in that class is DateTime.
The value I get from mongo is /\Date(number)/. Which is ok because this is what I'm suppose to return to the client.
The value that I get from mongo after I retrieve the data is ISODate(some number).
I get an exception: "Invalid JSON primitive: ISODate".
How can I configure mongoDB to save the DateTime like I got it i.e. /\Date(number)/?
Sorry L.B - I didn't noticed your answer but went straight to the answer I was given.
Here's the class I'm trying to deserialize:
public class EventDate
{
public EventDate()
{
}
public int? VenueConfigID { get; set; }
public string Category { get; set; }
public DateTime DateAndTime { get; set; }
public string DisplayDate { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string ShortNote { get; set; }
public string Home { get; set; }
public int? ID { get; set; }
public string Name { get; set; }
}
Here's how I deserialize it:
mongo = MongoServer.Create();
mongo.Connect();
db = mongo.GetDatabase("productionDB");
var col = db.GetCollection<BsonDocument>("eventDates");
var query = Query<PerformerDates>.EQ(ev => ev.PerformerID, performerId);
//MongoCursor<BsonDocument> performer = col.Find(query);
MongoCursor<BsonDocument> performer = col.FindAll();
JavaScriptSerializer js = new JavaScriptSerializer();
List<EventDate> finalMatchedDates = new List<EventDate>();
foreach (var p in performer)
{
//System.Threading.Tasks.Task<EventDate[]> obj2 = JsonConvert.DeserializeObjectAsync<EventDate[]>(p.Elements.ToList()[3].Value.ToString());
EventDate[] obj3 = JsonConvert.DeserializeObject<EventDate[]>(p.Elements.ToList()[3].Value.ToString());
}
mongo.Disconnect();
Solved!!
Eventually I solved it. I used a string instead of a DateTime. When I get it from the DB, I convert it to a DateTime and when I sent it back to the client I serialize it with the format of: /\Date()/
Just use BsonSerializer.Deserialize method.
MongoDB's serializer has a much higher performance over NewtonSoft's Json.Net or Microsoft's DataContractSerializer.
Very common occurring problem! One solution is to use JSON.NET.
See this answer for more help. Although you might be confused with JSON DateTime object but don't worry. It will work!
string json; // Assign JSON here.
var v = Newtonsoft.Json.JsonConvert.DeserializeObjectAsync<T>(json);

Setting variable types from CSV

var csv =
from line in File.ReadAllLines("C:/file.csv")
let customerRecord = line.Split(',')
select new Customer()
{
contactID = customerRecord[0],
surveyDate = customerRecord[1],
project = customerRecord[2],
projectCode = customerRecord[3]
};
public class Customer
{
public string contactID { get; set; }
public string surveyDate { get; set; }
public string project { get; set; }
public string projectCode { get; set; }
}
I'd like to be able to read the surveyDate as a DateTime in order to compare it with other DateTime fields I'm joining to the csv file.
I've tried just setting surveyDate as Date.Time in the class, and I've tried converting it in the select statement, but both fail with the following error:
FormatException: The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.
I do have to work with the csv file, so I can't add the data to sql server.
contactID,responseDate,project,projectID
1,6/4/2009,0-3 months,1
2,6/11/2009,0-3 months,1
You need to parse it when reading as well as changing the type. I'm not sure how you tried it in the first place. Also, use DateTime.ParseExact if you know the format.
var csv =
from line in File.ReadAllLines("C:/file.csv")
let customerRecord = line.Split(',')
select new Customer()
{
contactID = customerRecord[0],
surveyDate = DateTime.Parse(customerRecord[1]),
project = customerRecord[2],
projectCode = customerRecord[3]
};
public class Customer
{
public string contactID { get; set; }
public DateTime surveyDate { get; set; }
public string project { get; set; }
public string projectCode { get; set; }
}
Judging by the error you just posted, I think it's probably double-quoted. Try trimming the quotes:
DateTime.Parse(customerRecord[1].Trim('"'))
Right... Because you can never know what the input will be from the CSV you can't always try and implicitly convert the string to a DateTime and because you want to do the convert of a string within the select a way to do this is an extension method.
public static class StringExtensions
{
public static DateTime TryParseDate(this string strToParse)
{
DateTime dt = new DateTime();
DateTime.TryParse(strToParse, out dt);
return dt;
}
}
Then when you want to convert in the select do it like this:
var csv = from line in File.ReadAllLines("C:/file.csv")
let customerRecord = line.Split(',')
select new Customer()
{
contactID = customerRecord[0],
surveyDate = customerRecord[1].TryParseDate(),
project = customerRecord[2],
projectCode = customerRecord[3]
};
You have your own method. Hope this helps and works for you.
The string you want to parse will be passed to the method and then you can handle it and return a valid date time, handling incorrect inputs.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
See this link for an explanation
After changing Customer so that SurveyDate is a DateTime then:
select new Customer()
{
contactID = customerRecord[0],
surveyDate = DateTime.Parse(customerRecord[1]),
project = customerRecord[2],
projectCode = customerRecord[3]
};
You may need to use forms of Parse or ParseExact that take a format string, to be sure of the correct result. That format string depends on the format used in the file.
Alternatively, you could create a Parse static method on Customer:
public class Customer
{
public string contactID { get; set; }
public DateTime surveyDate { get; set; }
public string project { get; set; }
public string projectCode { get; set; }
public static Customer Parse(string line)
{
var parts = line.Split(',');
return new Customer{
contactID = parts[0],
surveyDate = DateTime.Parse(customerRecord[1]),
project = customerRecord[2],
projectCode = customerRecord[3]
};
};
Then:
var csv =
from line in File.ReadLines("C:/file.csv")
select Customer.Parse(line);
This has an advantage if obtaining a Customer from such a formatted string happens more than once in your code. It needlessly fills Customer with cruft if this is the only place you do it. Note I favour ReadLines over ReadAllLines to get a line at a time rather than read the whole thing before starting do produce customers.
Incidentally, .NET conventions favour capitals on property names. SurveyDate rather than surveyDate etc.
I've tried just setting surveyDate as Date.Time in the class, and I've tried converting it in the select statement, but both fail.
Well you need to do both. You need to change the property type (ideally fixing the naming at the same time to follow conventions) and change where you're setting it, probably using DateTime.ParseExact, specifying the format and probably the invariant culture.
(I'm assuming you know the format of the date in the file - I would strongly advise you to use DateTime.ParseExact rather than just letting the framework try various formats until it finds one which works.)
EDIT: Now that we've seen the file, it looks like you'd want either
DateTime.ParseExact(text, "d/M/yyyy", CultureInfo.InvariantCulture)
or:
DateTime.ParseExact(text, "M/d/yyyy", CultureInfo.InvariantCulture)
... but we can't tell which, as we don't know whether "6/4/2009" means April 6th or June 4th.
You should convert your customerRecord[1] string to a DateTime.
var csv =
from line in File.ReadAllLines("C:/file.csv")
let customerRecord = line.Split(',')
select new Customer()
{
contactID = customerRecord[0],
surveyDate = DateTime.Parse(customerRecord[1]),
project = customerRecord[2],
projectCode = customerRecord[3]
};
public class Customer
{
public string contactID { get; set; }
public DateTime surveyDate { get; set; }
public string project { get; set; }
public string projectCode { get; set; }
}

Categories

Resources