Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Assigning dates with C++ driver
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  9 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
George Thompson  
View profile  
 More options Oct 31 2012, 4:18 pm
From: George Thompson <george.ford.thomp...@gmail.com>
Date: Wed, 31 Oct 2012 13:18:12 -0700 (PDT)
Local: Wed, Oct 31 2012 4:18 pm
Subject: Assigning dates with C++ driver

I want to do this in C++

mongo::BSONObj doc = BSON(mongo::GENOID << "name" << "George" << "birthdate" << new Date(1990, 4, 15) );

which gives me

1>garden.cpp(59): error C2061: syntax error : identifier 'Date'
1>garden.cpp(59): error C2228: left of '.obj' must have class/struct/union
1>garden.cpp(59): error C2143: syntax error : missing ';' before ')'
1>garden.cpp(59): error C2143: syntax error : missing ';' before ')'

Which tells me I have no idea how to assign a date with the C++ driver. For the life of me, I couldn't find anything in the online docs or a google search except for a ticket requesting examples in the documentation.

So, what is the trick?


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jason Rassi  
View profile  
 More options Oct 31 2012, 7:12 pm
From: Jason Rassi <ra...@10gen.com>
Date: Wed, 31 Oct 2012 16:12:47 -0700 (PDT)
Local: Wed, Oct 31 2012 7:12 pm
Subject: Re: Assigning dates with C++ driver

You're looking for a mongo::Date_t object, which will get serialized with
BSON's datetime type.  Its constructor takes an integer representing
milliseconds since the epoch. See [1] for its definition.  Once you've
initialized one, you can pass it in directly to the BSON() macro in place
of where "new Date(...)" was in your snippet.

You also have other options for ways to generate BSON datetime values.
 Here's your example using C-style dates (see [2] for definitions of the
various BSONObjBuilder helper methods):

struct tm birthdate;
strptime("6 Dec 2001 12:33:45", "%d %b %Y %H:%M:%S", &birthdate);

mongo::BSONObjBuilder builder;
builder.genOID();
builder.append("name", "George");
builder.appendTimeT("birthdate", mktime(&birthdate));

mongo::BSONObj doc = builder.obj();

[1] https://github.com/mongodb/mongo/blob/master/src/mongo/bson/util/misc.h
[2] https://github.com/mongodb/mongo/blob/master/src/mongo/bson/bsonobjbu...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
George Thompson  
View profile  
 More options Oct 31 2012, 7:39 pm
From: George Thompson <george.ford.thomp...@gmail.com>
Date: Wed, 31 Oct 2012 16:39:46 -0700 (PDT)
Local: Wed, Oct 31 2012 7:39 pm
Subject: Re: Assigning dates with C++ driver

So, the trick is not to use the BSON helpers? There isn't a way to assign a
date with BSON? Or can I set the date to a BSONElement and then stream it
with BSON?

If not, I'll stop using BSON when building my BSONObjs. Doesn't this mean
BSON is fairly limited?

Thanks for your tips!

George


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jason Rassi  
View profile  
 More options Oct 31 2012, 8:50 pm
From: Jason Rassi <ra...@10gen.com>
Date: Wed, 31 Oct 2012 17:50:56 -0700 (PDT)
Local: Wed, Oct 31 2012 8:50 pm
Subject: Re: Assigning dates with C++ driver

> So, the trick is not to use the BSON helpers?

No, that wasn't what I was saying.  I presented two different solutions;
the first used the BSON() macro, and the second didn't.  I'll spell out the
first one more explicitly:

long long birthDateInMillisSinceEpoch = ...;
mongo::BSONObj doc = BSON(mongo::GENOID << "name" << "George" <<
"birthdate" << new mongo::Date_t(birthDateInMillisSinceEpoch));

You can generate "birthDateInMillisSinceEpoch" using POSIX functions like
the ones I called before, or Boost's Date-Time library, etc.

It's illustrative to see the BSONObjBuilder methods being used explicitly,
since the BSON() macro stream operator is implemented with BSONObjBuilder.
 To see a list of all of the different objects you can use the stream
syntax with, see all of the implementations of append() in the
bsonobjbuilder.h file I linked to earlier.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
George Thompson  
View profile  
 More options Oct 31 2012, 8:53 pm
From: George Thompson <george.ford.thomp...@gmail.com>
Date: Wed, 31 Oct 2012 17:53:38 -0700 (PDT)
Local: Wed, Oct 31 2012 8:53 pm
Subject: Re: Assigning dates with C++ driver

Yes -- I finally figured that out (slow, but I catch on). Working on Boost
(I'm on windows) right now.

Thanks so much!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Therefore  
View profile  
 More options Nov 1 2012, 7:31 pm
From: Therefore <thereforena...@gmail.com>
Date: Thu, 1 Nov 2012 16:31:22 -0700 (PDT)
Local: Thurs, Nov 1 2012 7:31 pm
Subject: Re: Assigning dates with C++ driver

This did the trick with Boost:

    #include "boost/date_time/posix_time/posix_time.hpp"    using namespace boost::posix_time;
    ptime epoch     = time_from_string("1970-01-01 00:00:00.000");
    ptime birthdate = time_from_string("2001-12-06 12:33:45");

    time_duration const diff = birthdate - epoch;
    long long birthDateInMillisSinceEpoch = diff.total_milliseconds();

    mongo::BSONObj doc = BSON(mongo::GENOID << "name" << "George" << "birthdate" << mongo::Date_t(birthDateInMillisSinceEpoch));

I didn't need the "new".

Does this look like a reasonable Boost solution?

Thanks!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jason Rassi  
View profile  
 More options Nov 2 2012, 1:34 pm
From: Jason Rassi <ra...@10gen.com>
Date: Fri, 2 Nov 2012 10:34:52 -0700 (PDT)
Local: Fri, Nov 2 2012 1:34 pm
Subject: Re: Assigning dates with C++ driver

Your solution has the right idea.  See [1] for a similar but more succinct
one (the snippet under the "Boost to Mongo" section of the question).  When
you're generalizing, make sure you handle dates before the epoch correctly
(these are represented by Date_t objects initialized with negative values).

Passing in the Date_t object to the << operator without calling "new" is
correct (I left it in as a typo when copy-pasting your original line).
 "new" returns a pointer, which C++ will implicitly cast to a bool here,
throwing away the date information you're trying to serialize (in addition
to creating a memory leak).

[1]
http://stackoverflow.com/questions/10973846/convert-between-boostposi...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Therefore  
View profile  
 More options Nov 2 2012, 4:09 pm
From: Therefore <thereforena...@gmail.com>
Date: Fri, 2 Nov 2012 13:09:35 -0700 (PDT)
Local: Fri, Nov 2 2012 4:09 pm
Subject: Re: Assigning dates with C++ driver

This is the generalization I came up with:

   // Create a mongo date (Date_t) from year, month, and day passed as
integers
  // (year = with century, month = 1 - 12, day = 1-31)
  mongo::Date_t MongoDate(const int &year, const int &month, const int &day)
  {
      boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
      try
      {
      boost::posix_time::ptime
ptime_date(boost::gregorian::date(year,month,day));
      boost::posix_time::time_duration const diff = ptime_date - epoch;
      long long ms = diff.total_milliseconds();
      return mongo::Date_t(ms);
      }
      catch (std::out_of_range& oor)
      {
          std::cerr << year << "-" << month << "-" << day << " is an
invalid date: " << oor.what() << endl;
          return mongo::Date_t(0);
      }
  }

(Note: Please ignore the absurdity of returning mongo::Date_t(0) -- I'm
either going to use Boost::Optional to return a NULL or stop using BSON and
handling the addition of dates with a function using BSONObjBuilder).

This works for the full range of boost dates, 1400 - 10000. I'm confused
why it works since Date_t is an unsigned long long.  However, after
executing "birthdate" << MongoDate(1960,4,16), the shell's db.personnel.find()
displays ISODate("1960-04-16T00:00:00Z") and "cout << doc.toString() << endl"
displays "new Date(-306460800000)". misc.h does have a "TODO: make signed".
I'm using 2.2.0.

I had tried to solve this before posting here using tm and mktime and never
had any luck. Replicating from the Stackoverflow link:

    boost::posix_time::ptime
ptime_date(boost::gregorian::date(year,month,day));
    std::tm tm_date = boost::posix_time::to_tm(ptime_date);
    std::time_t ms = mktime(tm_date);
    return mongo::Date_t(ms);

This didn't compile -- I believe it should be mktime(&tm_date). mktimereturns seconds whereas I intend to generalize this further by allowing
times including milliseconds. mktime returns "-1" with years less than
1970. I'm sure there is a way to finesse this to work properly, but I am
not seeing why the first solution isn't somewhat more intuitive. But I lack
experience in using "struct tm" and mktime, so I'm sure that is the source
of the solution's apparent deficiencies.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jason Rassi  
View profile  
 More options Nov 2 2012, 7:00 pm
From: Jason Rassi <ra...@10gen.com>
Date: Fri, 2 Nov 2012 16:00:02 -0700 (PDT)
Local: Fri, Nov 2 2012 7:00 pm
Subject: Re: Assigning dates with C++ driver

> I'm confused why it works since Date_t is an unsigned long long.

Your solution works because Date_t's member "millis" is interpreted as a
signed value when read, such as when MongoDB reads it as BSON off the wire
(your first example, with .find()), and in bson-inl.h's
BSONElement::toString (your second example, with cout).

> mktime returns "-1" with years less than 1970.

That's not strictly the case: mktime() attempts to convert its argument to
a time_t (which on 32-bit platforms is generally limited to dates from
~1901 to ~2038), and returns (time_t)-1 if it can't be represented as such.
 You're correct in that you can't use this solution if you need sub-second
precision.

Your pure-Boost solution is fine; it overcomes a number of POSIX's
limitations that you saw in the other approaches.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »