v0d1ch
v0d1ch

Reputation: 2748

C MongoDB driver DateTime update

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

Answers (1)

v0d1ch
v0d1ch

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

Related Questions