Reputation: 2748
Ok this is the scenario. I am reading txt file and inserting/updating (with bulk operations ) data to mongodb. Inserting part works fine since I am creating bson document in a loop and doing mongoc_bulk_operation_insert.
My date comes in a format of 11:37:17.253 SAST JUN 05 2015 so I run it trough the function that removes .253 and SAST and feed it to the convert_to_date function that you see down in the text.
This is how I create timestamp and append the date to the document:
int convert_to_date(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
return newTime;
}
return 0;
}
/* this is somewhere in a loop */
time_t t = convert_to_date(s1);
bson_append_time_t(doc, field_map[y], strlen(field_map[y]), t);
// and after all if insert is supposed to happen i call
// mongoc_bulk_operation_insert(bulk, doc);
// and mongoc_bulk_operation_execute(bulk, &reply, &error);
That part is just fine when I look at the database I get ISODate("2015-06-05T09:37:17.000Z")
So ther problem is when I try to update existing record.
When i do update i need to do a $set on all of the fields I want to update(upsert actually and I didnt find a way to update complete document at once) it looks like this:
//update document with sessionid
query = BCON_NEW("SessionId", BCON_UTF8(sid));
update = BCON_NEW("$set", "{", "SomeDateTimeField",
BCON_DATE_TIME(ystack[y]), "}");
mongoc_bulk_operation_update(bulk, query, update, true);
The value of ystack[y] is 1433497048 which is valid timestamp but i get in the db ISODate("1970-01-17T14:11:37.037Z") I also found an example online for inserting the whole bson object as date like this:
int64_t currentTime = time(NULL) * 1000;
bson_t *date = BCON_NEW("$date", BCON_DATE_TIME(currentTime));
bson_t *update = BCON_NEW("$set", "{", "last_sync_time", date, "}");
But this produces \u0001 in the DB instead of valid date. I cant tell what is causing this, so much frustration for something that should be straight forward. This is the libbson api for the reference
https://api.mongodb.org/libbson/current/index.html
and c driver api
http://api.mongodb.org/c/1.1.8/
Upvotes: 0
Views: 568
Reputation: 2748
Ok I found the solution myself, should have read the api more carefully :)
The BCON_DATE_TIME accepts milliseconds instead of seconds which I passed to it.
I actually tried to multiply by 1000 before but since my var was int it could not store the correct value.
I had to declare it as
unsigned long long
Here is the changed code just for reference
long convert_to_long(char *dateString)
{
struct tm *parsedTime;
time_t rawTime;
time_t newTime;
int hour, minutes, seconds, millis, year, month, day;
if (sscanf(dateString, "%d:%d:%d %d %d %d",
&hour, &minutes, &seconds, &month, &day, &year) != EOF) {
time(&rawTime);
parsedTime = localtime(&rawTime);
parsedTime->tm_year = year - 1900;
parsedTime->tm_mon = month - 1;
parsedTime->tm_mday = day;
parsedTime->tm_hour = hour;
parsedTime->tm_min = minutes;
parsedTime->tm_sec = seconds;
newTime = mktime(parsedTime);
unsigned long long millis = newTime * 1000;
return millis;
}
return 0;
}
Upvotes: 1