user3248331
user3248331

Reputation: 105

Doctrine, symfony2 correct column type to use for calculating hours

I am recording peoples hours and minutes worked, and then adding them together to produce a total amount worked for a certain period. What is the best column type to use for this in Doctrine? My initial thought was just to use integer, but this will require back and forth conversion into Time formats.

What is the best practice for these sorts of time calculations?

Upvotes: 1

Views: 719

Answers (2)

qooplmao
qooplmao

Reputation: 17759

I would recommend either storing as an integer of minutes or as a custom "time" field that would automatically create a "Time" value object that would give you access to the methods that you need. The value object would be a bit more complicated.

The benefit of storing as minutes would be that you could do maths related searches (SUM, AVG, etc) directly rather than having to call each object individually and add them up that way.

On top of using the integer method you could create the same "Time" value object that took the time in minutes and then get that from your object like..

/**
 * Get minutes worked
 *
 * @return integer
 */
public function getMinutes()
{
    return $minutes;
}

/**
 * Set working minutes
 *
 * @param integer $minutes
 * @return $this
 */
public functions setMinutes($minutes)
{
    $this->minutes = $minutes

    return $this;
}

/**
 * Get worked Time
 *
 * @return Time
 */
public function getTime()
{
    if (null === $this->minutes) {
        return $minutes;
        // Or return Time::fromMinutes(0);
    }

    return Time::fromMinutes($this->minutes);
}

And then in your value object..

class Time
{
    private $minutes;

    /**
     * Private constructor so as to use more meaningful static calls
     *
     * @param integer $minutes
     */
    private function __construct($minutes)
    {
        if ($is_int($minutes)) {
            throw new \Exception(sprintf(
                'Minutes expected to be an "integer", "%s" given',
                gettype($minutes)
            ));
        }

        $this->minutes = $minutes;
    }

    /**
     * Construct object from minutes
     *
     * @param integer $minutes
     * @return Time
     */
    public static function fromMinutes($minutes)
    {
        return self($minutes);
    }

    /**
     * Get time in minutes
     *
     * @return integer
     */
    public function getMinutes()
    {
        return $this->minutes;
    }

    /**
     * Get time in hours and minutes string in 00:00 format
     *
     * @return string
     */
    public function getAsString()
    {
        return sprintf(
            '%02d:%02d',
            floor($this->minutes / 60),
            $this->minutes % 60
        );
    }

    //...
    Any other methods
}

So your form could just take the minutes (or a 00:00 string with a data transformer) and then you could call it like $job->getTime()->getAsString() (after checking the time was not null, or alternatively returning an empty Time object).

Upvotes: 1

Ivan M
Ivan M

Reputation: 330

I think that for you case need to use "datetime" type filed. You can convert DateTime object in different formats

    /**
 * @var \DateTime $start
 *
 * @ORM\Column(type="datetime")
 */
protected $start;

/**
 * @var \DateTime $end
 *
 * @ORM\Column(type="datetime")
 */
protected $end;

/**
 * @return \DateTime
 */
public function getStart()
{
    return $this->start;
}

/**
 * @param \DateTime $start
 */
public function setStart(\DateTime $start)
{
    $this->start = $start;
}

/**
 * @return \DateTime
 */
public function getEnd()
{
    return $this->end;
}

/**
 * @param \DateTime $end
 */
public function setEnd(\DateTime $end)
{
    $this->end = $end;
}

Upvotes: 1

Related Questions