Doctrine Mongodb ODM and DateTime query

JuCachalot picture JuCachalot · Dec 23, 2011 · Viewed 10.7k times · Source

I could use some help on this problem. I'm creating an application using Symfony2 + mongodb + doctrine. I just want to use Doctrine ODM to query all the users who have been logged in the last 5 minutes. I have a User collection with a date field called date_last_login.

So I try to use the querybuilder like that:

<?php
// Creating a DateTime object and susbtract 5 min from now
// local time is 15:40:05, timezone: 'Europe/Paris'
$_dateTime = new \DateTime();
$_interval5Min = new \DateInterval('PT5M');
$_dateTime->sub($_interval5Min);

$query = $this->createQueryBuilder('User')
                ->field('date_last_login')->gte($_dateTime)
                ->getQuery();
                ->execute();

When I looked at the assembled query using symfony2 profiler, here is what I got:

db.User.find({ "date_last_login": { "$gte": new Date("Fri, 23 Dec 2011 15:30:05 +0100") } });

It seems fine except that the date is 10 minutes earlier rather than 5 minutes? I just don't get it. If I dump my php DateTime object, date is correct: 2011-12-23 15:35:05 (five minutes before 15:40).

So I tried to assemble the same query without substracting any minutes and this time, everything is fine:

<?php
// local time is 15:50:00
$query = $this->createQueryBuilder('User')
            ->field('date_last_login')->gte(new \DateTime())
            ->getQuery();
            ->execute();

// query is ok:
db.User.find({ "date_last_login": { "$gte": new Date("Fri, 23 Dec 2011 15:50:00 +0100") } });

What am I doing wrong ? Thank you for your help!

Answer

ahmed hamdy picture ahmed hamdy · Apr 14, 2014

To create query builder for get data when date_last_login great than 5 minutes there 3 ways

1) create DateTime object with your datetime format and get timestamp from DateTime object then create MongoDate object :

$timeBefore5MinutesAgo  = new \DateTime(date('Y-m-d H:i:s',\time() - 5 * 60));
$mongoDateBefore5MinutesAgo = new \MongoDate($currentDateWithTime->getTimestamp());

$query = $this->createQueryBuilder('User')
    ->field('date_last_login')->gte($mongoDateBefore5MinutesAgo)
    ->getQuery();
    ->execute();

2) create MongoDate object and use strtotime to convert you`r datetime format to timestamp :

$mongoDateBefore5MinutesAgo = new \MongoDate(strtotime(date('Y-m-d H:i:s',\time() - 5 * 60)));

$query = $this->createQueryBuilder('User')
    ->field('date_last_login')->gte($mongoDateBefore5MinutesAgo)
    ->getQuery();
    ->execute();

3) only in case Doctrine 2 ODM , you can just create DateTime object with you`r datetime format:

$timeBefore5MinutesAgo  = new \DateTime(date('Y-m-d H:i:s',\time() - 5 * 60));

$query = $this->createQueryBuilder('User')
              ->field('date_last_login')->gte($timeBefore5MinutesAgo)
              ->getQuery();
              ->execute();

all 3 ways will create query this:

db.User.find({ "date_last_login": { "$gte": new ISODate("2014-03-15T19:35:08+02:00") } });