Handle time change (summer- and default time) in MongoDB with C# driver - c#

I have a centralized logging service written in C#. This service receives log entries (in JSON string) and add them in a MongoDB collection. I use the official C# MongoDB driver and MongoDB Version 3.0.
Let's say I have a document with this basic structure (and example):
{
"_id" : ObjectId("562c2785a075b738c484ad99"),
"Service" : "WebServer A",
"Description" : "User has logged in",
"SourceTime" : ISODate("2015-10-25T00:41:15.469Z")
}
As you can see in this document I have a date field called "SourceTime". This UTC format doesn't tell me whether the document is created in summer- (+02:00) or in default time (+01:00).
I would like to ask you what's the best way to store a date field with an ISODate object without having problems with summer- and default time?
Is it better to store an ISODate with following format in C#?
{
"SourcTime" : ISODate("2015-10-25T01:41:15.469+01:00")
}
If yes, does anyone has an example how to achieve that with C#?
At the moment, I add a document as follows:
// parse String _document to a BsonDocument
BsonDocument document = BsonDocument.Parse(_document);
// Change SourceTime field to a DateTime object
var TimeElem = document.GetElement("SourceTime").Value.ToString();
DateTime newTime = DateTime.Parse(TimeElem);
// Update document
document.Set("SourceTime", newTime.ToUniversalTime()); // result ISODate("2015-10-25T00:41:15.469Z")
// Add to MongoDB
var collection = _database.GetCollection<BsonDocument>(_collectionName);
collection.InsertOneAsync(document);
Thank you very much for your help. Very appreciate it.
Regards

MongoDB uses a Bson Date which does not store the timezone within the date -
The official BSON specification refers to the BSON Date type as the UTC datetime.
https://docs.mongodb.org/manual/reference/bson-types/#date
The ISODate("2015-10-25T01:41:15.469+01:00") is just a javascript helper method to allow you to convert between an ISODate and a BsonDate so the offset within the string just change converted back to a UTC time.
If you require the timezone or the offset you will need to manually store this within the document, and convert it back after deserialization.

Related

DocumentDB Query to find created date

I want to retrieve the documents with only documentID and document Created DateTime details. I am able to get the DocumentID by following query but how can we get the Document created datetime.
select c.id from c
However, along with id I need to get the document created date also
Any help on this appreciated !
I am able to get the DocumentID by following query but how can we get
the Document created datetime.
From this official doc , the automatically generated properties of the document when it is created consists only of the following: _rid,_etag,_ts,_self,id.
_ts represents last updated timestamp of the resource, so if this document has not been updated, then this time is the createTime. You could query it via Select c.id,c._ts from c.
So, maybe you need to log createTime by yourself when you create documents so that you could query the createTime later.
Hope it helps you.
The id , _ts or other custom properties like DocumentReadingCreatedDate are all properties in the document which is not divided into system details or non-system details. Just some of the properties I mentioned above are the fields that cosmosdb will automatically generate for you.
So you just need to use sql : select c._ts from c to find the newest update time of this document. You could get a long type data such as 1520216339 ,then you could convert it into datetime format such as Sun Jan 18 22:16:56 CST 1970 in your program.
If your documents have been updated and you must get the create time of the document, you can't use _ts field. You could only use your custom field DocumentReadingCreatedDate.
The _ts is a Unix Timestamp value.
You need to convert it. The following C# sample will do it.
private static DateTime UnixTimeStampToDateTime(long unixTimeStamp)
{
System.DateTime dtDateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp);
return dtDateTime;
}
Or you can create a UFD that you can use in your query, The following is one that will work
function epochToDate (ts) {
return new Date(ts*1000);
}
You would use it as follows:
SELECT * FROM c WHERE udf.epochToDate(c._ts) == ....

MongoDB C# Driver, httprequest.json to BSON, then insertMany

I want to replace a stock price data AccessDB with a MongoDB using MongoDB c# driver.
The download data using xmlhttprequest as json string is shown below (2 dates only):
[{"date":"2016-01-04T00:00:00.000Z","close":2.77,"high":2.82,"low":2.63,"open":2.77,"volume":32516771},{"date":"2016-01-05T00:00:00.000Z","close":2.75,"high":2.8,"low":2.64,"open":2.77,"volume":12972260},....]
I have studied the c# driver documentation and conducted web searches, but can't find anything that I can get to work. I could parse the each document (i.e, price for a symbol and a date) in the json string and insertOne as in the BsonDocument snippet below.
I would think that json or BSON methods exist that make to appropriate conversions to accomplish a BSON insertMany() DB load.
Please help me get up the curve by finding appropriate info and learn how to do this.
Thank you.
The below works with manual conversion from above JSON data for 1 date
BsonDocument stkDoc = new BsonDocument
{
{"symbol","AMD"},
{"date","2016-01-04T00:00:00.000Z"},
{"close",2.77},
{"high",2.82},
{"low",2.63},
{"open",2.77},
{"volume",32516771}
};
_client = new MongoClient();
_db = _client.GetDatabase("stkprices");
var collection = _db.GetCollection("stkdata1");
collection.InsertOne(stkDoc);

Inserting DateTime into MongoDB

Is there something which I need to take into consideration when Im trying to serialize data into Mongo database which is keyed by DateTime?
My data looks like this SortedDictionary<DateTime, Data> Data and the problem Im facing is that the DateTime key have time part equal to 00:00:00 but after insertion into Mongo it is ISODate("2003-11-24T23:00:00Z") sometimes T22:00:00Z.
I preaty sure the problem is not with data Im inserting into DB I checked on every possible place if time part is always equal to 00:00:00 and it is.
mongo stores dates in UTC format by default so it seems you are in different time zone hence the difference
Are you converting from a string to a datatime in C#? Maybe that is causing it to be off by an hour because of daylight savings, local time, or UTC.
The C# mongodb driver handles the format. You could quickly test using something like an integer to be sure it's not your format prior to insertion. MongoDB DateTime Format

To Get Data that its type is Date in C#

In my SQL database, I have BeginDate column of type date (so I want to get only day,month,year).
I add data into database in C#.
I look at Table_Data and everything is fine (for example BeginDate = 05/04/2014).
But when I get this data from database in C# with
string a= dt.Rows[i]["BeginDate"].ToString()
result is: a= 05/04/2014 12:00:00 AM
Why?
I can remove hour in string a with any methods. But why? I want to get only 05/04/2014 from database.
This is a display problem, not a data problem. Use the Formatting features of DateTime.ToString() to display the date in the format that you want.
If the data is coming out of the database in string form, use DateTime.Parse on it first.
Reference
Standard Date and Time Formats
Custom Date and Time Formats

Issue with dates in WCF service and in JavaSerializer decoder

One of the nastiest problems working across time zones :)
Here is my problem:
I have code that passes date into WCF via JSON object and I use "short" format where it contains only milliseconds since 1970 with no time zone. This DateTime parsed by WCF just FINE
I store date into SQL Server Database. Example: 2011-06-07 22:17:01.113 - date as I see it in SQL Server and this is perfectly fine since I store everything in UTC. So, it's (-5) time zone and date looks right.
I load date field into my object using EF and inside object property says it is 22:17 and Kind=Unspecified which is OK again, it is loaded from SQL, I know it is UTC but code doesn't know that so it loads this date as Unspecified.
I return this object to WCF client. It can be XML or it can be JSON. Here is what happen. When I JSON(this is what client specifies) - I get this: 1307503021113-0500 for date. If we convert first portion to DateTime using SQL:
SELECT DATEADD(ss, 1307503021,
'1970-01-01')
2011-06-08 03:17:01.000
Part above already wrong, no? If we apply -5hr adjustment we will be back to 22:17pm which already utc time? This part already confusing to me. But what even worse - when I deserialize using JavaScriptSerializer - I see DateTime value in newly inflated object saying UTC kind and 3:17am
var oSerializer = new JavaScriptSerializer();
var returnValue = (T)oSerializer.Deserialize(s, typeof(T));
I'm all puzzled already and I wonder if it's possible to force WCF and other serializer/deserializers to NOT do any time offsets and stuff? I'd rather format all dates for display manually and I want to store UTC dates in database.
UPDATE:
Looks like WCF thinks that if DateKind is Unspecified than it's LOCAL.
I did this: After I got objects from EF I specified Kind:
foreach (var tu in tripUpdates)
{
tu.DeviceTime = DateTime.SpecifyKind(tu.DeviceTime, DateTimeKind.Utc);
}
That fixed it - now when WCF serves object it doesn't include timezone which is GREAT. Now my main question is there any way to specify Kind on EF entities somehow so I don't have to manually specifiy kind for every date in service?
When you get the datetime via a SELECT statement always set the DateTime.Kind to UTC. This way WCF/XML will not try to adjust the time.

Categories

Resources