Convert seconds to timestamp?

Asked

Viewed 1,055 times

4

I am creating a PHP script to generate a json from a caption file webvtt, take the beginning and the end that are in the format minuto:segundo.milisegundo or if the video is too big they come as hora:minuto:segundo.milisegundo for future JS comparisons in the future where the video is playing need to compare these values with the currentTime video which in turn delivers time in seconds segundos.milisegundos and to facilitate such a comparison I would like my PHP to already deliver the start and end time of each legend already in the same format as the currentTime of the video, how can I?

Here’s an example:

$start = "00:05.570";
$fim = "00:09.700";

In the above example it would be easy to distinguish that the currentTime would be 5.570 and 9.700 how do I convert PHP to this format?

  • 1

    @Leocaracciolo not understood, has an example in the question of two values and how they should be delivered by PHP

  • I’m not sure that timestamp understands milliseconds for value conversion....

  • I don’t know if timestamp would be the correct term, I’ve looked in some places but I always find the opposite of what I need

  • I want to convert a time period that is format in hh:ii:ss. u to ss. u only, ie convert time into seconds

  • Correct Leo 00:05,570 is 5 seconds and 570 ms

  • In your example the first two 00 representing the time, is a dynamic value that may or may not be passed to the variable, if the time to be converted is less than 1 hour, it will not reach it in the full format

  • You want to convert all time in seconds?

Show 2 more comments

2 answers

3


Solution

A solution using regular expressions would be, making only the second value mandatory:

function convert($value)
{
    if (preg_match("/(((?P<hours>\d+)\:)?(?P<minutes>\d{1,2})\:)?(?P<seconds>\d{1,2})(\.(?P<milis>\d+))?/", $value, $matches))
    {
        $hours   = intval($matches["hours"]);
        $minutes = intval($matches["minutes"]);
        $seconds = intval($matches["seconds"]);
        $milis   = isset($matches["milis"]) ? intval($matches["milis"]) : 0;

        return sprintf("%d.%d", $hours * 3600 + $minutes * 60 + $seconds, $milis);
    }

    return false;
}

// Entrada: horas:minutos:segundos.milis
echo convert("123:12:42.9"), PHP_EOL;   // 443562.9

// Entrada: horas:minutos:segundos.milis
echo convert("01:20:03.7345"), PHP_EOL; // 4803.7345

// Entrada: horas:minutos:segundos.milis
echo convert("0:01:56.23"), PHP_EOL;    // 116.23

// Entrada: minutos:segundos.milis
echo convert("00:05.570"), PHP_EOL;     // 5.570

// Entrada: minutos:segundos.milis
echo convert("00:09.700"), PHP_EOL;     // 9.700

// Entrada: minutos:segundos
echo convert("00:05"), PHP_EOL;         // 5.0

// Entrada: segundos.milis
echo convert("4.55"), PHP_EOL;          // 4.55

// Entrada: segundos
echo convert("12"), PHP_EOL;            // 12.0

See working on Ideone.


Explanation

The solution was entirely based on PHP’s native function preg_match:

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

The first parameter, $pattern, is the regular expression we will analyze. The second, $subject, is the string on which we will apply the regular expression and the third parameter, $matches, will be a array with the values of string that match the pattern defined in the regular expression.

The regular expression used is divided into four parts:

/(((?P<hours>\d+)\:)?(?P<minutes>\d{1,2})\:)?(?P<seconds>\d{1,2})(\.(?P<milis>\d+))?/
  +-----------------+-----------------------+-------------------+------------------+
      (horas)               (minutos)             (segundos)          (milis)

Regular expression: hours

The regular expression for hours, ((?P<hours>\d+)\:)?, may be reduced to (\d+\:)?, which means one or more digits (\d+) followed by a character : (\:) optional (?). The part ?P<hours> serves only to name the group; i.e., if there is a value that matches this pattern, create in $matches the index hour with the value matched. For example, if the input is 01:20:03.7345, there will be $matches["hours"] equal to 01. If time is not set, $matches["hours"] will be false (because we defined that it was optional in regular expression).

Regular expression: minutes

Vide hours (exactly the same logic, just changing the group name to minutes, ((?P<minutes>\d{1,2})\:)?). The quantifier of + for {1,2}, because minutes will have 1 or 2 digits: 1 if it is less than 10 minutes (whereas 0 may not be added to the left) or 2 digits when 10 to 59 minutes.

Regular expression: seconds

It is basically the same expression used for minutes, differentiating only that it will be mandatory, so there will be no character ? in the end, (?P<seconds>\d{1,2}).

Regular expression: Milis

For the milliseconds, (\.(?P<milis>\d+))?, stays: if defined (?), must start with the character . (\.) followed by one or more digits (\d+), capturing this group under the name of milis. Note that the \. is not part of the nominated group as we only want the numerical value, otherwise, $matches["milis"] would be something like .570 instead of 570.

  • 1

    Opa liked the solution with expression, I’ll give a studied in the answer, I’m trying to learn to use expressions so answers are very good, if it is not ask too much you could break and explain the parts of the expression used in if?

  • @Leoletto see if it’s clear enough.

  • Oops, I’ll test there

  • Tested, which was already good, got even better. Dynamically tested in http://kithomepage.com/sos/segundost.php

  • 1

    @Andersoncarloswoss I’m doing this here, but the error if the input is minutes:seconds.milliseconds, if the time in seconds is 00 it does not from the error, but when increases the function generates a value that does not correspond to the past time: https://ideone.com/VeP7eR

  • 1

    @Leoletto really did it. If this happened because the value of optional minutes also, when informed, it matches the value of hours, then if you enter with the value "01:05", instead of leaving "601 + 1", exit "36001 + 5". To tidy up, just move a parentheses, making that if informed the time, must be informed the minutes (which makes sense), so when informed only the minutes, is correct. I have already changed the answer.

  • 1

    In revisions the answer is very clear which parentheses I changed, if I have difficulty locating it.

Show 2 more comments

1

Personally I would prefer to work with the function DateTime native to PHP

You would have to set the date to 01/01/1970, the rest he would do the conversion...

echo timestamp('00:00:30.570')."<br/>"; //30.57
echo timestamp('00:10:30.570')."<br/>"; // 630.57
echo timestamp('12:10:30.570')."<br/>"; // 43830.57

function timestamp($horario){
    list($sec, $msec) = explode('.', $horario);
    $date = '01/01/1970 '.$sec;
    $dateTime = DateTime::createFromFormat('d/m/Y H:i:s', $date, new DateTimeZone('GMT'));
    $timestamp = $dateTime->getTimestamp();
    return $timestamp+($msec/1000);
}

Ai would be in charge of you define better how you would like the return, depends a lot on your need and how you intend to work from here / Forward

  • As an example, taking into account that the string to convert can be just min:seg.ms without the time at the beginning?

  • In this case I would have to do a regex to check whether the received string is in the hh:ii:ss.uu format, correct?

  • With entry 00:09.700 no time giving error PHP Fatal error: Call to a Member Function getTimestamp() on a non-object in

Browser other questions tagged

You are not signed in. Login or sign up in order to post.