84

I have a string and I need to find out whether it is a unix timestamp or not, how can I do that effectively?

I found this thread via Google, but it doesn't come up with a very solid answer, I'm afraid. (And yes, I cribbed the question from the original poster on the aforementioned thread).

hakre
  • 193,403
  • 52
  • 435
  • 836
RHPT
  • 2,560
  • 5
  • 31
  • 43
  • from reading the thread i would say the short answer is no. you may well be able to check for something that is definitely not valid but valid, doesn't look like it. – PurplePilot Mar 26 '10 at 16:13
  • Can you please add some more explanation as to why you need to validate the string or what you are planning to do with it, once it is validated. – Gordon Mar 26 '10 at 17:20

13 Answers13

108

Ok, after fiddling with this for some time, I withdraw the solution with date('U') and suggest to use this one instead:

function isValidTimeStamp($timestamp)
{
    return ((string) (int) $timestamp === $timestamp) 
        && ($timestamp <= PHP_INT_MAX)
        && ($timestamp >= ~PHP_INT_MAX);
}

This check will only return true if the given $timestamp is a string and consists solely of digits and an optional minus character. The number also has to be within the bit range of an integer (EDIT: actually unneeded as shown here).

var_dump( isValidTimeStamp(1)             ); // false
var_dump( isValidTimeStamp('1')           ); // TRUE
var_dump( isValidTimeStamp('1.0')         ); // false
var_dump( isValidTimeStamp('1.1')         ); // false
var_dump( isValidTimeStamp('0xFF')        ); // false
var_dump( isValidTimeStamp('0123')        ); // false
var_dump( isValidTimeStamp('01090')       ); // false
var_dump( isValidTimeStamp('-1000000')    ); // TRUE
var_dump( isValidTimeStamp('+1000000')    ); // false
var_dump( isValidTimeStamp('2147483648')  ); // false
var_dump( isValidTimeStamp('-2147483649') ); // false

The check for PHP_INT_MAX is to ensure that your string can be used correctly by date and the likes, e.g. it ensures this doesn't happen*:

echo date('Y-m-d', '2147483648');  // 1901-12-13
echo date('Y-m-d', '-2147483649'); // 2038-01-19

On 64bit systems the integer is of course larger than that and the function will no longer return false for "2147483648" and "-2147483649" but for the corresponding larger numbers.


(*) Note: I'm not 100% sure, the bit range corresponds with what date can use though

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 1
    I *think* negative timestamps are valid. `time_t` is signed in Linux at least. – Yacoby Mar 26 '10 at 17:03
  • 1
    It didn't work for a value of 1276664400, probably due to the value being passed back as a string as opposed to a integer. – Justin Yost Jul 16 '10 at 16:17
  • 1
    @jtyost It works as explained and demanded by the OP. It checks whether the **string** is a valid Unix Timestamp. Passing in an **integer** will obviously not return true. Passing in `"1276664400"` will. – Gordon Jul 16 '10 at 16:27
  • +1 Good work. It's nessesary to check the value for later using with date(). – algorhythm Jun 19 '13 at 12:08
  • 2
    php time() doesn't seem to pass the check above. http://php.net/manual/en/function.time.php – allencoded Apr 06 '15 at 17:01
  • 3
    @allencoded yes, by design. `time` returns an integer. The OP asked to *check whether the **string** is a unix timestamp*. – Gordon Apr 06 '15 at 17:12
  • This fails for "114004965600" – Peon Jun 02 '16 at 09:37
  • @DainisAbols no, it doesn't. [It gives true for any PHP 5.5.0 - 5.6.22, hhvm-3.9.1 - 3.12.0, 7.0.0 - 7.0.7](https://3v4l.org/pr2iD) on 64bit machines. I assume you are on a 32bit machine. That is expained in the answer though. – Gordon Jun 02 '16 at 10:22
  • What about 0. Is 0 a valid time? isValidTimeStamp(0)? A call to "new \Carbon\Carbon(0)" fails. – Shriganesh Shintre Jul 08 '16 at 15:37
  • @ShriganeshShintre 0 is a valid timestamp. However, the function above will only allow "0" as per the OPs requirement. – Gordon Jul 08 '16 at 15:52
  • @Gordon - What are your thoughts on this one: https://gist.github.com/sepehr/6351385 where they have added `OR is_float($timestamp)) ? $timestamp : (string) (int) $timestamp;` ? – Abela Jul 25 '17 at 17:01
  • Ihave one question: What's happen if you have 64bit PHP? – Ivijan Stefan Stipić May 06 '19 at 13:00
  • Add ```$timestamp = strval($timestamp);``` in the function to get the timestamp in string, that will do the trick in 64bits. – Sadee Dec 03 '20 at 21:35
42

As a unix timestamp is a integer, use is_int(). However as is_int() doesn't work on strings, we check if it is numeric and its intergal form is the same as its orignal form. Example:

( is_numeric($stamp) && (int)$stamp == $stamp )
Yacoby
  • 54,544
  • 15
  • 116
  • 120
  • To express timestamps with milliseconds, the unixtimestamp may also be a floating point in some areas, right? – Patrick Cornelissen Mar 26 '10 at 16:06
  • @Patrick A Unix time stamp is usually an integer due to floating point precision. I have never come across it represented as a real number. – Yacoby Mar 26 '10 at 16:09
  • 2
    The OP has a string, so is_int won't do. Has to be is_numeric if any. – Gordon Mar 26 '10 at 17:16
  • @Gordon Yay for the inconstancies of PHP. Fixed. – Yacoby Mar 26 '10 at 17:36
  • @Yacoby What do you mean that is_int won't work on strings? I tried is_int("booga") and it returned false, is this something that was updated with newer versions of PHP? – SimaPro Aug 25 '13 at 20:46
  • 3
    @SimaPro is_int('345345') returns FALSE, where is_numeric('345345') returns TRUE. is_int() just tests the type of whatever you pass it, is_numeric() tests the actual contents. – Syntax Error May 24 '14 at 21:26
  • @SimaPro "not enter the dragon > way of the dragon". – dewd Mar 10 '22 at 00:07
20

I came across the same question and created the following solution for my self, where I don't have to mess with regular expressions or messy if-clauses:

/**
 * @param string $string
 * @return bool
 */
public function isTimestamp($string)
{
    try {
        new DateTime('@' . $string);
    } catch(Exception $e) {
        return false;
    }
    return true;
}
simplychrislike
  • 436
  • 4
  • 9
10

this looks like the way to go:

function is_timestamp($timestamp) {
    if(strtotime(date('d-m-Y H:i:s',$timestamp)) === (int)$timestamp) {
        return $timestamp;
    } else return false;
}

you could also add a is_numeric() check and all sort of other checks.
but this should/could be the basics.

Nijboer IT
  • 1,178
  • 1
  • 13
  • 18
  • This code works, but it will throw a notice if you pass it anything other than a valid timestamp. – Syntax Error May 24 '14 at 21:30
  • What is the notice about than? (i had an typo in it. use d-m-Y instead of American m-d-Y !!) you can modify it whit Throwing exceptions en stuff. – Nijboer IT May 25 '14 at 09:23
  • It's an E_NOTICE that you've passed an invalid value. The formatting of date() doesn't affect this. Some folks don't mind scripts throwing notices and just turn off error reporting for that level but many (myself included) prefer not to throw or silence even E_STRICT notices unless we really have to. – Syntax Error May 25 '14 at 15:24
  • adding `is_int($time) &&` inside if will solve error reporting. To avoid potential ambiguity better use `'Y-m-d H:i:s'` format as [per docs](http://php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes) (3rd note) – Pedro Sanção Apr 01 '15 at 17:24
  • 1
    use ctype_digit($timestamp) && inside the if statement instead of is_int($timestamp). Is_int will return false if the passed in $timestamp is in the form of a string. So, passing is_int('123') will return false. – Dimitar Darazhanski Jun 25 '15 at 18:02
  • Add `(is_int($timestamp) || ctype_digit($timestamp)) &&` to the beginning of your if statement to catch the possibility of it being a string of numbers or an actual integer. – JaredC Dec 29 '18 at 19:23
8

Improved answer to @TD_Nijboer.

This will avoid an exception be thrown if the supplied string is not a time stamp:

function isTimestamp($timestamp) {
    if(ctype_digit($timestamp) && strtotime(date('Y-m-d H:i:s',$timestamp)) === (int)$timestamp) {
        return true;
    } else {
        return false;
    }
}
cabrerahector
  • 3,653
  • 4
  • 16
  • 27
Dimitar Darazhanski
  • 2,188
  • 20
  • 22
  • Used this one for years but realised it doesn't work well with Daylight saving time (DST) and some Timezone. For example `1635638410` & `Europe/Paris` Timezone will return false. – Axi Nov 02 '21 at 09:18
4

This doesn't account for negative times(before 1970), nor does it account for extended ranges(you can use 64 bit integers so that a timestamp can represent a value far after 2038)

$valid = ctype_digit($str) && $str <= 2147483647;
goat
  • 31,486
  • 7
  • 73
  • 96
3

or

if ($startDate < strtotime('-30 years') || $startDate > strtotime('+30 years')) {
    //throw exception
}
alex toader
  • 2,300
  • 1
  • 17
  • 20
  • This did a very nice trick. Even adding more years in upper border would still work. – М.Б. Mar 11 '22 at 13:38
  • This is the most concise AND practical solution in 99% of real-world use cases where timestamps technically range from Thu Jan 01 1970 00:00:00 UTC thru Jan 19, 2038, at 3:14 a.m. UTC. – Eric P Jun 13 '22 at 12:28
1

You want to check if a string contains a high number?

is_numeric() is the key

Or convert it to DateTime and do some checks with it like an expected date range.

Muhammad Hassaan
  • 7,296
  • 6
  • 30
  • 50
Patrick Cornelissen
  • 7,968
  • 6
  • 48
  • 70
1

If you might think to replace this solution with is_numeric(), please consider that php native function provides false positives for input strings like "1.1", "0123", "0xFF" which are not in timestamp format.

Community
  • 1
  • 1
Alex Matiushkin
  • 169
  • 1
  • 3
0
    //if anything else than digits inside the string then your string is no timestamp 
    //in which case maybe try to get the timestamp with strtotime

    if(preg_match('/[^\d]/', $str)) {
        $str = strtotime($str);

        if (false === $str) {
            //conversion failed - invalid time - invalid row
            return;
        }
    }
alex toader
  • 2,300
  • 1
  • 17
  • 20
0

In PHP for checking if a timestamp represents a valid Gregorian date this worked for me:

function checkdateTimestamp($timestamp) {
    return checkdate((int)date('m',$timestamp),(int)date('d',$timestamp),(int)date('Y',$timestamp));
}
MTset
  • 90
  • 5
0

I do two checks from timestamp, both utc and usually higher than 11/13 digit and after control

// Is Timestamp control function
function isTimestamp($x,$lenMax = 11,$compare = 30){
if (!ctype_digit($x)) return false;
$x = strlen($x) >= $lenMax ? $x / 1000 : $x;
if ($x < strtotime("-{$compare} years") || $x > strtotime("+{$compare} years")) {   
    return false;
}
return true;

}

// Timestamp UTC usually take from javascript -> Date.Now() -> 1618362206593
echo check_timestamp(1618362206593); // Return -> true
// or that stand time()
echo check_timestamp(1618359229); // return -> true
// UTC
echo check_timestamp(5618362206593); // Return -> false
// or that stand time()
echo check_timestamp(5618359229); // return -> false
Clary
  • 544
  • 1
  • 7
  • 8
0

Another possibility:

$date_arg = time();
$date_is_ok = ($date_arg === strtotime(date('c', $date_arg)));
Marek Grzenkowicz
  • 17,024
  • 9
  • 81
  • 111
Chris
  • 1