Ensuring Unix time in PHP - php

My code assumes that zero represents the beginning of the Unix epoch, 1970-01-01 00:00. I upgraded an installation of PHP and now, all of a sudden, zero represents 1970-01-01 01:00 (as verified with date('Y-m-d H:i', 0)). So apparently there is a time zone matter. I put the same code into a sandbox and got 1969-12-31 16:00. I have several unit tests that are broken as a result of this. Time zones do not and should not come into play here.
How can I ensure that date-time functions such as date() always converts zero to 1970-01-01 00:00 regardless of the time zone setting on the particular installation?

Using gmdate() you'll always get 1970-01-01 00:00 for 0, no matter what timezone your server is in:
<?php
date_default_timezone_set('Europe/Berlin');
echo "Europe/Berlin:\n";
echo "gmdate: ".gmdate('d.m.y H:i', 0) . "\n";
echo "date: ".date('d.m.y H:i', 0) . "\n";
date_default_timezone_set('America/Los_Angeles');
echo "\nAmerica/Los_Angeles:\n";
echo "gmdate: ".gmdate('d.m.y H:i', 0) . "\n";
echo "date: ".date('d.m.y H:i', 0) . "\n";
/* OUTPUT:
Europe/Berlin:
gmdate: 01.01.70 00:00
date: 01.01.70 01:00
America/Los_Angeles:
gmdate: 01.01.70 00:00
date: 31.12.69 16:00
*/
https://3v4l.org/FechC

You need to set the default time zone to GMT if you want to use date() like that. For example:
date_default_timezone_set('GMT');
echo date('Y-m-d H:i [I] [e] [O]',0);
The above will show (no matter what the server has been set to):
1970-01-01 00:00 [0] [GMT] [+0000]
Without the date_default_timezone_set('GMT'), or even set to Europe/London, you will get a different result at different times of the year.
From the PHP manual;
date — Format a local time/date
gmdate — Format a GMT/UTC date/time

The solution is to get the timezone setting, set it aside, change the timezone to UTC, perform the calculations, and reset the timezone to its original setting.
So if my original function looked like this:
public function format($argument = null)
{
// Perform some calculations involving date() and strtotime().
return $result;
}
Now it looks like this:
public function format($argument = null)
{
$timezone = date_default_timezone_get();
date_default_timezone_set('UTC');
$result = ...; // Perform some calculations involving date() and strtotime().
date_default_timezone_set($timezone);
return $result;
}

Related

Datetime in PHP Script

I use a PHP script for a banlist that fetches the date and time, but I have an error and don't know how to convert it to "normal" time.
It lists me only the date : 01.01.1970 um 00:00 Uhr
The script part from this:
//Convert Epoch Time to Standard format
$datetime = date("d.m.Y \\u\\m H:i \\U\\h\\r", $row['expires']);
echo "<td>$datetime</td>";
This is the entry from the mysql db: http://fs1.directupload.net/images/141208/9ugjslm8.jpg
Dont know if it helps?
Have anyone an idea to solve this?
LINK: http://pastebin.com/r0dXg8FX
The row comes from an plugin. for example: $row['name'] , $row ['banner'], $row['reason'] this comes all from the plugin
It lists me only the date : 01.01.1970 um 00:00 Uhr
That simply means you are thinking of $row['expires'] incorrectly. That is not a UNIX Timestamp value and is producing an invalid date. It means the value essentially evaluates to 0, which is Jan 1st 1970 in UNIX time
date() requires you to send a valid Unix timestamp to it (INT 11), is that what you have in database for that field? or it is a date time field?
Try this
echo date("d.m.Y \\u\\m H:i \\U\\h\\r", "2014-10-12"); //invalid
echo date("d.m.Y \\u\\m H:i \\U\\h\\r", time()); //valid: current unix timestamp
Based on this image (that you have given in deleted answer) you have milliseconds. Divide milliseconds with 1000 to get seconds.
Probably something like this:
$datetime = date('d.m.Y \u\m H:i \U\h\r', $row['expires'] / 1000);
But, if you get year 1970, that means that you are on 32bit machine, and your fetched INT is out of range. In this case you could just cut last 3 numbers with string function substr():
$datetime = date('d.m.Y \u\m H:i \U\h\r', substr($row['expires'], 0, -3));
Convert the date to UNIX timestamp first. Try with -
$datetime = date("d.m.Y \\u\\m H:i \\U\\h\\r", strtotime($row['expires']));
echo "<td>$datetime</td>";

date returning different results in different versions of php

I have a date A and B.
I wanted to get the hours/minutes between them. Like:
date('h:i', strtotime(B) - strtotime(A));
But I get strange results:
echo date('h:i', strtotime('2014-01-01') - strtotime('2014-01-01'));
// echoes: 01:00 (!)
date_default_timezone_set('Europe/London');
$date = new DateTime();
$A = $date->format('Y-m-d H:i:s'); echo '<br />';
$date->modify("+64 minutes");
$B = $date->format('Y-m-d H:i:s'); echo '<br />';
echo date('h:i', strtotime($B) - strtotime($A));
// echoes 02:04 (!)
Live example for the previous code:
Why is this and how to get the expected result?
This is correct behavior
Why? Think of it: strtotime('2014-01-01') - strtotime('2014-01-01') is zero - but date() expects timestamp as second parameter. So that means, you're trying to get date from zero-point timestamp. And that point is different in different timezones. Your London TZ has +01 offset, that's why 0-point timestamp is 01 Jan 1970 01:00:00 - and that's why date('h:i', 0) is 01:00
Try to set, for example, Moscow zone:
date_default_timezone_set('Europe/Moscow');
$date = new DateTime();
$A = $date->format('Y-m-d H:i:s');
$date->modify("+64 minutes");
$B = $date->format('Y-m-d H:i:s');
echo date('h:i', strtotime($B) - strtotime($A));//04:04
-you'll see exactly 04:04 - because current offset for Moscow is +03 (so 03 hours + 64 minutes modification)
What date expects as its second parameter is an absolute timestamp, which it then formats in the specified format. You outputting h:i means you're outputting only the hour:minute part of a complete year, month, day, hour, minute, second timestamp. If you want to format the relative difference between two timestamps, date is the wrong function to use. The result is expected, since you're actually dealing with absolute timestamps in timezones.

strtotime is different with timezone

Seems I don't quite understand much the function strtotime. My case is I would like to compare the current time (now) with a specific time on specific timezone
For example the specific time is "this Monday at 14:00:00" at the timezone "America/New_York":
$specificTime = strtotime("monday this week 14:00:00 America/New_York");
My current code is:
$now = strtotime("now America/New_York");
if ($now > $specificTime) {
//do something
}
But I have figured it out that $now above is 6 hours ahead with current time. The number 6 I guess from offset -05:00 of America/New_York, plus with 1 hour daylight saving.
it should remove timezone out of $now, it will work correctly:
$now = strtotime("now");
if ($now > $specificTime) {
//do something
}
Could someone give the explain why strtotime("now America/New_York") is 6 hours ahead with strtotime("now), why they are not equivalent? really confused.
P.S: I am on GMT+07:00.
Simple debugging:
<?php
$now = strtotime("now America/New_York");
echo date('r', $now);
// Thu, 28 Nov 2013 16:39:51 +0100
... shows that such command is doing this:
Calculate local time in my default time zone (10:39:51 +0100)
Return timestamp that corresponds to 10:39:51 in New York time (-0500)
Doing date manipulation with strings is terribly complicated. Just imagine you'd try to do math with string functions: strtofloat('one plus square root of half hundred')—there'd be plenty of room for mistakes. So my advise is to keep it simple and only use with simple expressions when there's some benefit, such as strtotime('+1 day').
If you need to work with different time zones, I suggest you use proper DateTime objects. If you choose to work with Unix timestamps, forget about time zones: Unix timestamps do not have time zone information at all.
You can use DateTime for this. I believe settings a timezone in strtotime is not valid.
$specificTime = new DateTime("monday this week 14:00:00", new DateTimeZone("America/New_York")));
$now = new DateTime("now", new DateTimeZone("America/New_York"));
You can then compare unix timestamp with this:
if ($now->getTimestamp() > $specificTime->getTimestamp()) {
// do something ...
}
There is time offset between each timezone.
strtotime() function will return the Unix timestamp according the timezone.
It will use the default time zone unless a time zone is specified in that parameter.
The default time zone it the return value of date_default_timezone_get();
Look the code below:
<?php
// UTC
echo date_default_timezone_get(), "\n";
// 2013-11-28 14:41:37
echo date('Y-m-d H:i:s', strtotime("now America/New_York")), "\n";
// 2013-11-28 09:41:37
echo date('Y-m-d H:i:s', strtotime("now")), "\n";

How to store expiration time?

I want to store the expiration time in database. I am using the below code to store expiration time with +1 year.
$cdate = time();
$date = $cdate + 365*24*60*60;
$date = date("Y-m-d H:i:s",$date);
but its not storing the correct time it stores 2014-08-10 07:55:14 but time on storing is 2014-08-10 01:25:14.
Aslo not sure its Am or Pm .
Thanks.
Time/date functions in PHP are using timezones to determine your local time. So if your server is in timezone GMT+6 that means that the date() function will return you the date/time that is 6 hours before GMT.
You can check the date_default_timezone_set() function manual to find out how PHP is selecting your timezone.
To set your timezone, you can use date_default_timezone_set() before calling date function or you can set you php.ini setting date.timezone to your timezone.
For the second part of your question - when formatting time using the date() function the H format character will return 24-hour format of an hour with leading zeros.
try this
<?php
$timezone1 = "America/Los_Angeles";
date_default_timezone_set($timezone1);
$cdate = time();
$date1 = $cdate + 365*24*60*60;
$date = date("Y-m-d H:i:s a",$date1);
echo $date;
$timezone = "Asia/Calcutta";
date_default_timezone_set($timezone);
$cdate = time();
$date1 = $cdate + 365*24*60*60;
$date = date("Y-m-d H:i:s a",$date1);
echo $date;
?>
you can set timezone for your location.And also refer this codepad-FIDDLE
As others have mentioned, it is calculating the time based on your server (local) time.
I suggest you store the time in GMT and then adjust it to your desired timezone as necessary.
You can use strtotime() to calculate 1 year from now (no need to calculate it yourself) and use gmdate() to get the timestamp in GMT.
echo "Next Year in local time: ". date("Y-m-d H:i:s", strtotime("+1 year")) ."\n";
echo "Next year in GMT: " . gmdate ("Y-m-d H:i:s", strtotime ("+1 year")) . "\n";
// Output:
// Next Year in local time: 2014-08-10 15:25:09
// Next year in GMT: 2014-08-10 08:25:09

Strange behavior of PHP time math: Why is strtotime() returning negative numbers?

I'm trying to do some very basic time math - basically, given inputs of time and distance, calculate the speed. I chose to use strtotime() to convert the time inputs into seconds - but I'm getting some bizarre results.
For example, given this sample program:
<?php
$t1 = strtotime("3:15:00",0);
$t2 = strtotime("1:00:00",0);
$t3 = strtotime("2:00:00",0);
$t4 = strtotime("9:00:00",0);
echo $t1 . "\n";
echo $t2 . "\n";
echo $t3 . "\n";
echo $t4 . "\n";
?>
Why do I get these results?
$ php test.php
-56700
-64800
-61200
-36000
Update:
Since no one said it explicitly, let me explain the bug in the above function. I had assumed that passing a time of zero to strtotime() would cause it to generate time stamps derived from midnight, 12/31/1969, UTC - which sounds odd, but would work for my purposes.
What I hadn't counted on was that strtotime() takes time zones into account when converting strings, and my server is apparently 5 hours behind UTC. On top of that, because of the time zone shift, PHP then interprets the times as relative to the day before the epoch which means it is interpreting my times as occurring relative to December 30th, 1969 instead of the 31st, resulting in negative numbers...
It appears that Eugene is correct - if I want to calculate just the elapsed time, I can't use the built in time functions.
If you want to do something like that, I think you want to just do some math on the time strings themselves and convert them to a number of seconds, like this:
<?php
function hmstotime($hms)
{
list($hours, $minutes, $seconds) = explode(":",$hms);
return $hours * 60 * 60 + $minutes * 60 + $seconds;
}
?>
Apparently with just bare times PHP is assigning the date December 31, 1969. When I ran this:
echo date('F j, Y H:i:s', $t1) . "\n";
echo date('F j, Y H:i:s', $t2) . "\n";
echo date('F j, Y H:i:s', $t3) . "\n";
echo date('F j, Y H:i:s', $t4) . "\n";
I got this:
December 31, 1969 03:15:00
December 31, 1969 01:00:00
December 31, 1969 02:00:00
December 31, 1969 09:00:00
Remember that strtotime returns a UNIX timestamp, which is defined as the number of seconds since January 1, 1970. By definition a UNIX timestamp refers to a specific month/day/year, so despite the name strtotime is not really intended for bare times without dates.
Because strtotime() outputs the number of seconds relative to the second argument (in your case, the Unix epoch (December 31, 1969 19:00:00)).
The negative numbers is expected because "3:15:00" is 56700 seconds before the Unix epoch.
Try it without the second parameter. That's supposed to be a timestamp for the returned time to be relative to. Giving it 0 means you're asking for a timestamp relative to the Unix epoch.
In response to your comment:
It's not documented functionality, but I use strtotime("HH:MM") all the time, and it returns a timestamp relative to the current time. I guess if you want to be sure though, you could do this:
strtotime("3:15:00",time());
strtotime() without a second argument gets the time from the supplied string and fills in the blanks from the current date:
echo date('Y-m-d H:i:s', strtotime("3:15:00"));
-> 2009-06-30 03:15:00
With a second argument it calculates the date relative to the second argument:
echo date('Y-m-d H:i:s', strtotime("3:15:00", 0));
-> 1970-01-01 03:15:00
To calculate the difference between two timestamps in seconds, you can just do this:
echo strtotime("3:15:00") - strtotime("3:00:00");
-> 900
Edit: Of course taking into account which is the bigger number:
$t1 = strtotime("3:15:00");
$t2 = strtotime("3:30:00");
$diff = max($t1, $t2) - min($t1, $t2);
$diff = abs($t1 - $t2);
Or something of that nature...

Categories