How to query with the datetime value using LINQ to XML? - c#

I am developing window phone 7 application in silverlight. I am new to the silverlight. I am also new to LINQ to XML. In my application the user select the date & submit some transaction details into the application. The details gets stored in XML File. I am using the custom date control in my application for the date selection as follows
private void DatePicker_ValueChanged(object sender, DateTimeValueChangedEventArgs e)
{
AppObj = Application.Current as App;
AppObj.date = (DateTime)EntryDate.Value;
}
Then the value of AppObj.date gets stored in the XML file. Sometimes I use the DateTime.Now to store the date in the XML File. Now I want to generate the report of submitted transaction details by querying through LINQ to XML. I want to generate the report for today's date, current week & current month. For today's date report I am using the following code
public void GetTransactionObjects(String strXMLFile, DateTime VDateTime)
{
XDocument doc = null;
XMLFileManager XMLDocObj = new XMLFileManager();
doc = XMLDocObj.LoadXMLFile(strXMLFile);
var vTransaction = from s in doc.Descendants("Transaction")
.Where(x => x.Element("Current_Date").Value == VDateTime.ToShortDateString())
select new Transaction(s);
this.Clear();
AddRange(vTransaction);
}
The Transaction class contains the following constructor.
public Transaction(XElement xElement)
{
Transaction_ID = Convert.ToInt32(xElement.Element("Transaction_ID").Value.ToString());
TransactionType_ID = Convert.ToInt32(xElement.Element("TransactionType_ID").Value.ToString());
Alphabet_ID = Convert.ToInt32(xElement.Element("Alphabet_ID").Value.ToString());
ID = Convert.ToInt32(xElement.Element("ID").Value.ToString());
SubCategory_ID = Convert.ToInt32(xElement.Element("SubCategory_ID").Value.ToString());
Item_ID = Convert.ToInt32(xElement.Element("Item_ID").Value.ToString());
Currency_ID = Convert.ToInt32(xElement.Element("Currency_ID").Value.ToString());
InputTypeMethod_ID = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Principle = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Interest = Convert.ToInt32(xElement.Element("Interest").Value.ToString());
ROI = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Amount = Convert.ToInt32(xElement.Element("InputTypeMethod_ID").Value.ToString());
Current_Date = Convert.ToDateTime(xElement.Element("Current_Date").Value.ToString());
}
In the XML File the value gets stored for date & time. The value gets stored as follows
<Transactions>
<Transaction>
<Transaction_ID>0</Transaction_ID>
<TransactionType_ID>0</TransactionType_ID>
<Alphabet_ID>3</Alphabet_ID>
<ID>0</ID>
<SubCategory_ID>0</SubCategory_ID>
<Item_ID>0</Item_ID>
<Currency_ID>3</Currency_ID>
<InputTypeMethod_ID>0</InputTypeMethod_ID>
<Principle>0</Principle>
<Interest>0</Interest>
<ROI>0</ROI>
<Amount>5000</Amount>
<Current_Date>2010-12-31T18:08:23.433+05:30</Current_Date>
</Transaction>
</Transactions>
Look at the node
<Current_Date>2010-12-31T18:08:23.433+05:30</Current_Date>
The date format is yyyy-mm-dd.
Now how should I write the following query to get all the submitted transaction details for today's date ?
var vTransaction = from s in doc.Descendants("Transaction")
.Where(x => x.Element("Current_Date").Value == VDateTime.ToShortDateString())
select new Transaction(s);
Similarly how should I write the query to get all the transaction details for the current week & current month? Can you please provide me any code or link through which I can resolve the above issue ? If I am doing anything wrong then please guide me.

Don't use Convert.ToDateTime or ToShortDateString etc with LINQ to XML. Use the conversions which already exist in XAttribute and XElement. For example:
DateTime today = DateTime.Today;
var query = doc.Descendants("Transaction")
.Where(x => ((DateTime) x.Element("Current_Date")).Date == today)
.Select(x => new Transaction(s));
(You should use the conversion operator in your Transaction constructor too.)

Related

Issue deserializing a date represented as a string in document from Cosmos DB

I currently have a C# application that queries Cosmos DB. In the database everything is stored as strings. When I query the container for the document and pull out the information it looks like the deserialization process is treating it like a date and its applying the Date Time Offset. Strange part is this process of querying the DB never converts it to a date? I would like it to just pass through the app as its stored in Cosmos.
Here is the document shape in Cosmos:
{
"id": "uniqueId",
"MyDate" : "2021-07-24T23:59:00+0000"
}
Here is the code that connects to CosmosDB
using(var client = new CosmosClient("EndPoint","Key")
{
string sqlQueryText = "Select * From c Where .... ";
QueryDefinition querySQL = new QueryDefination(sqlQueryText);
var container = client.GetContainer("databaseId", "ContainerId");
var iii = container.GetItemQueryIterator<Document>(querySQL);
var myList = new List<Document>();
while(iii.HasMoreResults)
{
FeedResponse<Document> currentRS = iii.ReadNextAsync().Result;
foreach(Document doc in currentRS)
{
myList.Add(doc);
}
}
}
Here is the Output of the this process in C#, By output I mean if you look at the myList Object and inspect the Mydate Property you will see this string below.
"07/24/2021 19:59:00"
which is the date & time with the date time offset.
How do I prevent this?
This application should just pass the string straight through with no regard for "Real Type".
I would just like to get "2021-07-24T23:59:00+0000"

DateTimeOffset: TZ Offset is reset to +00:00 when fetching data from LiteDb collection

When inserting, the offset is OK, however when retrieving the document, it's resetting to +00:00
Property:
public DateTimeOffset CreatedOn { get; set; }
Insert:
user.CreatedOn = DateTimeOffset.Now; // 01/20/2021 6:05:21 PM +05:30
col.Insert(user);
col.EnsureIndex(x => x.Username);
Find:
using (var db = _liteDbConnection.Create() as LiteDatabase)
{
var col = db.GetCollection<AuthUser>(USERS_COLLECTION);
return col.FindOne(x => x.UserId == userId);
}
user.CreatedOn becomes
01/20/2021 6:05:21 PM +00:00
Am I doing something wrong?
From the documentation
Following the BSON specification, DateTime values are stored only up to the miliseconds. All DateTime values are converted to UTC on storage and converted back to local time on retrieval.
It doesn't look like there's actual DateTimeOffset support. (Personally I think it's a terrible idea to convert to local time on retrieval, but that's a slightly different matter.) Additionally, it looks like it's not really converting to local time properly, given the incorrect offset of 0.
I would suggest avoiding using DateTimeOffset with LiteDb until it's really supported (maintaining the offset).
This happens because LiteDB stores a DateTimeOffset using value.UtcDateTime. This is unfortunate, but it can't be changed due to compatibility. However, you can override this behavior by creating a custom serializer:
BsonMapper.Global.RegisterType<DateTimeOffset>
(
serialize: obj =>
{
var doc = new BsonDocument();
doc["DateTime"] = obj.DateTime.Ticks;
doc["Offset"] = obj.Offset.Ticks;
return doc;
},
deserialize: doc => new DateTimeOffset(doc["DateTime"].AsInt64, new TimeSpan(doc["Offset"].AsInt64))
);

How to store ISO time into mongodb with timestamp being 0000000 using C#?

I want to store a DateTime instance into MongoDB using C#. As mongodb uses ISO 8601 as format, the date which I am passing is getting stored with a timestamp which is making querying using that date field a nightmare. I tried DateTime.Now, DateTime.UtcNow, BsonDateTime object but all are saving with current timestamp only. Is there a way using which I can make my date field to store date and rest as Zeros,
Thanks
Piyush Kumar
You can set up a class map for your class to only store the date part of the datetime with the following code:
BsonClassMap.RegisterClassMap<Order>(map =>
{
map.MapProperty(x => x.Date)
.SetSerializer(DateTimeSerializer.DateOnlyInstance);
});
then when execute the following
var client = new MongoClient();
var database = client.GetDatabase("test");
var collection = database.GetCollection<Order>("orders");
await collection.InsertOneAsync(new Order
{
Name = "MyOrder", Date = DateTime.UtcNow.Date
});
we'll get the following in the database
> db.orders.find().pretty()
{
"_id" : ObjectId("5ed8fb7050eb018e5ee13e73"),
"Date" : ISODate("2020-06-04T00:00:00Z")
}

How can I perform OrderBy using LINQ on XML data?

I have data in an XML file as follows:
<history>
<history-item id="1">
<history-url>www.google.com/ncr</history-url>
<history-date>29/06/2017</history-date>
<history-time>5:27:25PM</history-time>
</history-item>
<history-item id="2">
<history-url>www.yahoo.com</history-url>
<history-date>10/03/2017</history-date>
<history-time>5:30:25PM</history-time>
</history-item>
<history-item id="4">
<history-url>www.google.com/ncr</history-url>
<history-date>23/01/2014</history-date>
<history-time>5:27:25PM</history-time>
</history-item>
<history>
My goal is to group and order this data based on history-date.
I am using the following code in order to achieve this:
XDocument history = XDocument.Load("history.xml");
var details =
from c in history.Descendants("history-item")
group c by c.Element("history-date").Value into d
select new
{
Value = d.Key,
Rows = d.Elements("history-url")
};
details = details.OrderBy(c => c.Value);
However, the problem is that - the date is only sorted by the day i.e, dd.
When I try to print it, the output is:
10/03/2017
23/01/2014
29/06/2017
The desired output is:
23/01/2014
10/03/2017
29/06/2017
Any help is appreciated!
However, the problem is that - the date is only sorted by the day
This is because c.Element("history-date").Value expression produces a string, not a DateTime object. Hence, OrderBy puts these strings in lexicographical order, giving an appearance of sorting by day as long as single-digit days have zero prefixed to them.
You can fix this by parsing these strings when you get them, or right before ordering if you would rather keep them as strings in the output:
...
select new
{
Value = DateTime.ParseExact(d.Key, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None)
, Rows = d.Elements("history-url")
};
You need to convert c.value to an actual date. as it stands it is just a string.
details = details.OrderBy(c => Convert.ToDateTime(c.Value));
details = details.OrderBy(c => DateTime.ParseExact(c.Value, "dd/MM/yyyy", CultureInfo.InvariantCulture));

String was not recognized as a valid DateTime - Whats wrong?

I have been getting an annoying littler error and cannot for the life of me figure out why it is being cause. I have an xml file where i am storing data, as shown below.
- <EmployeeFinance>
<EmployeeEmploy_Id>5584</EmployeeEmploy_Id>
<EmpPersonal_Id>30358</EmpPersonal_Id>
<No_DaysWorked>30</No_DaysWorked>
<Date_Appointment>17/02/2012</Date_Appointment>
<Date_Employment>02/05/1984</Date_Employment>
<Date_Termination>01/01/0001</Date_Termination>
<Payperiod_StartDate>01/01/2013</Payperiod_StartDate>
<Payperiod_EndDate>31/01/2013</Payperiod_EndDate>
<BatchNumber>38</BatchNumber>
<PAYE_ToDate_Computed>0</PAYE_ToDate_Computed>
<Income_Tax_RateID>0</Income_Tax_RateID>
<NIS_RateID>0</NIS_RateID>
<NIS_weeks_worked>0</NIS_weeks_worked>
</EmployeeFinance>
If you look at the date nodes, Payperiod_StartDate,Payperiod_EndDate, Date_Appointment etc. They all have the same format. Now in my C# code, when i write my query to select from the xml file i get the String was not recognized as a valid DateTime error. WHen i comment out all the other dates and leave start_date, it works. They are the same format , i cant see what i am doing wrong. Please help me.
var context = new SSPModel.sspEntities();
XElement xelement = XElement.Load(GlobalClass.GlobalUrl);
XDocument doc = XDocument.Load(GlobalClass.GlobalUrl);
var query = from nm in xelement.Elements("EmployeeFinance")
select new EmployeeEmploy
{
Employee_Personal_InfoEmp_id = (int)nm.Element("EmpPersonal_Id"),
Substantive_designation = (int)nm.Element("Position_Id"),
Grade_Id = (int)nm.Element("Grade_Id"),
PositionTotal_PtBasic = (double)nm.Element("Sum_AllPosition"),//part of basic
GradeTotal_PtBasic = (double)nm.Element("Sum_AllGrade"), //part of basic
Housing_Allowance = (double)nm.Element("Housing"),
Base_Pay = (double)nm.Element("Base_Pay"),
startDate = (DateTime)nm.Element("Payperiod_StartDate"),
endDate = (DateTime)nm.Element("Payperiod_EndDate"),
Date_of_Appointment = (DateTime)nm.Element("Date_Appointment"),
Date_of_Employment = (DateTime)nm.Element("Date_Employment"),
Termination_date_actual = (DateTime)nm.Element("Date_Termination"),
Base_Pay_Currency = (string)nm.Element("Currency"),
Exchange_rate = (double)nm.Element("Exchange_Rate")
};
var x = query.ToList();
foreach (var xy in x) {
Debug.WriteLine(xy.endDate);
}
Because 17/02/2012 is not a valid date, however, 02/17/2012 is. The date will be parsed as mm/dd/yyyy. One option is to use DateTime.ParseExact to parse a date with the dd as the first set of numbers. e.g.
var startDate = DateTime.ParseExact("17/02/2012", "dd/MM/yyyy", null);
The debugger will show you that nm.Element("Payperiod_EndDate").ToString() gives you a string that includes the xml tags for that element. Try the following instead:
startDate = DateTime.ParseExact(nm.Element("Payperiod_EndDate").Value, "dd/MM/yyyy", null)

Categories