php unixtime, time() and timezones [duplicate] - php

I just want to check if time() returns a UTC/GMT timestamp or do I need to use date_default_timezone_set()?

time returns a UNIX timestamp, which is timezone independent. Since a UNIX timestamp denotes the seconds since 1970 UTC you could say it's UTC, but it really has no timezone.
To be really clear, a UNIX timestamp is the same value all over the world at any given time. At the time of writing it's 1296096875 in Tokyo, London and New York. To convert this into a "human readable" time, you need to specify which timezone you want to display it in. 1296096875 in Tokyo is 2011-01-27 11:54:35, in London it's 2011-01-27 02:54:35 and in New York it's 2011-01-26 21:54:35.
In effect you're usually dealing with (a mix of) these concepts when handling times:
absolute points in time, which I like to refer to as points in human history
local time, which I like to refer to as wall clock time
complete timestamps in any format which express an absolute point in human history
incomplete local wall clock time
Visualise time like this:
-------+-------------------+-------+--------+----------------+------>
| | | | |
Dinosaurs died Jesus born Y2K Mars colonised ???
(not to scale)
An absolute point on this line can be expressed as:
1296096875
Jan. 27 2011 02:54:35 Europe/London
Both formats express the same absolute point in time in different notations. The former is a simple counter which started roughly here:
start of UNIX epoch
|
-------+-------------------+------++--------+----------------+------>
| | | | |
Dinosaurs died Jesus born Y2K Mars colonised ???
The latter is a much more complicated but equally valid and expressive counter which started roughly here:
start of Gregorian calendar
|
-------+-------------------+-------+--------+----------------+------>
| | | | |
Dinosaurs died Jesus born Y2K Mars colonised ???
UNIX timestamps are simple. They're a counter which started at one specific point in time and which keeps increasing by 1 every second (for the official definition of what a second is). Imagine someone in London started a stopwatch at midnight Jan 1st 1970, which is still running. That's more or less what a UNIX timestamp is. Everybody uses the same value of that one stopwatch.
Human readable wall clock time is more complicated, and it's even more complicated by the fact that it's abbreviated and parts of it omitted in daily use. 02:54:35 means almost nothing on the timeline pictured above. Jan. 27 2011 02:54:35 is already a lot more specific, but could still mean a variety of different points on this line. "When the clock struck 02:54:35 on Jan. 27 2011 in London, Europe" is now finally an unambiguous absolute point on this line, because there's only one point in time at which this was true.
So, timezones are a "modifier" of "wall clock times" which are necessary to express a unique, absolute point in time using a calendar and hour/minute/second notation. Without a timezone a timestamp in such a format is ambiguous, because the clock struck 02:54:35 on Jan. 27 2011 in every country around the globe at different times.
A UNIX timestamp inherently does not have this problem.
To convert from a UNIX timestamp to a human readable wall clock time, you need to specify which timezone you'd like the time displayed in. To convert from wall clock time to a UNIX timestamp, you need to know which timezone that wall clock time is supposed to be in. You either have to include the timezone every single time with each such conversion, or you set the default timezone to be used with date_default_timezone_set.

Since PHP 5.1.0 (when the date/time functions were rewritten), every
call to a date/time function will generate a E_NOTICE if the timezone
isn't valid, and/or a E_WARNING message if using the system settings
or the TZ environment variable.
So in order to get a UTC timestamp you should check what the current timezone is and work off of that or just use:
$utc_str = gmdate("M d Y H:i:s", time());
$utc = strtotime($utc_str);

http://us3.php.net/time
"Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)."
So I believe the answer to your question is yes.

From the documentation
Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).

One of the comments claimed: "both time() and strtotime(gmdate("M d Y H:i:s", time())) return the same result"
Since I wasn't sure about that, I ran a test:
$now = strtotime(gmdate("Y-m-d H:i:s", time()));
$now2 = time();
echo ' now='.$now.' now2='.$now2.' diff='.($now - $now2);
Output was:
now=1536824036 now2=1536806036 diff=18000
Diff is 18000 seconds = 5 hours = the timezone offset for the server running the test.

Related

Why strtotime subtracts 2 hours automatically?

I used strtotime("YYYY-MM-DD H:i:s") and this gave me a time 2 hours automatically subtracted.
eg: strtotime("2016-05-11 00:00") gave me int(1462917600) this is 2 hours negative to what I have input.
Which is: 2016-05-10 22:00 when i reconvert.
Why is this?
From the docs:
Each parameter of this function uses the default time zone unless a time zone is specified in that parameter.
So my guess is that you're in a time zone where 2016-05-11 00:00:00 local is 2016-05-10 22:00:00 UTC.
The integer result will always be in "seconds since the Unix epoch" which uniquely identifies an instant in time. To convert either to that or from that, you should consider the time zone you want to use.

PHP and timezone

I am using strtotime() to get a timestamp from a date and time string. I will be running strtotime() during the summer (daylight savings) to give me a timestamp of a winter date (non-daylight savings).
In the winter, I will need to convert my timestamp to a readable date using date() -- will it be the same date/time I put into strtotime() during the summer?
On each one of my pages, I am setting my timezone by date_default_timezone_set with my city.
So, running this during the summer (daylight savings):
date_default_timezone_set('America/Los_Angeles');
echo strtotime("Dec 1 2014 8:00 am");
Gives me a certain timestamp 1417449600.
Will running this during the winter (non-daylight savings) return 8:00am as I need it to do?
date_default_timezone_set('America/Los_Angeles');
echo date("g:ia",1417449600);
Yes. If the timezone you set is doesn't explicitly say whether it's standard or daylight-savings time, it automatically determines the state of DST from the time that you give it and the rules for when the timezone switches into and out of DST.
Yes. A UNIX timestamp such as 1417449600 represents a completely, globally, universally unique point in time, independent of fussy timezone notation. There's only one "December 1st 2014 8 am in Los Angeles", which is the same point in time as "December 1st 2014 17:00 CET" and a number of other local notations across the world. The UNIX timestamp 1417449600 expresses that point in time, regardless of whatever your wall clock says exactly.
When you format this unique point in time back to a more human readable format using date(), it figures out what exactly the time must be formatted at based on the set timezone. It won't change based on what the time or DST settings are now.

Why is date() applying DST incorrectly?

I am trying to convert a human-readable time of 7am into a timestamp in PHP for calculation and manipulation purposes. The timestamp gets created correctly as 25200, but the date() function strangely converts the timestamp back to 08:00 when I use London as the timezone, 08:00 (correctly) when using Berlin, but 09:00 when using Athens.
I cannot understand why it does not return 07:00 and why it should be the same as Berlin. My server is in Germany and I am in London, might that have something to do with it? Hardly, since I have the same problem on my XAMPP stack here in London on my laptop.
date_default_timezone_set('Europe/London');
$time_readable = 7;
$time_stamp = $time_readable * 60 * 60;
echo $time_stamp;
echo date('H\:i',$time_stamp);
I even preceded my code with
date_default_timezone_set('UTC');
date_default_timezone_set('Europe/London');
but the problem persists.
What have I overlooked?
My PHP version on the server is 5.2.12 on the German production machine and 5.3.1 on my UK laptop XAMPP stack.
You seem to have a fundamental misunderstanding of what a timestamp is and how they work. You are also not understanding DST properly as it is laced with political changes to how it is applied.
However, to answer your specific question
I cannot understand why it does not return 07:00 and why it should be the same as Berlin.
Your timestamp represents 07:00 UTC on 1st January 1970. The reason setting the timezone to 'Europe/London' changes the time to 08:00 is because the UK was running the British Standard Time experiment which kept the UK on UTC + 1 from 27 October 1968 to 31 October 1971. Therefore the local time in London at 07:00 UTC on 1st January 1970 was 08:00.
I would recomend that your timestamps should always be complete timestamps that represent the full date and time. Trying to represent times only is the road to pain.
I also recomend learning to use the DateTime classes as they will handle all of this for you transparently.

DateTime using incorrect timezone

In my application I'm trying to calculate the time left until midnight GMT (UK time). At the moment I'm doing this:
$now = new DateTime();
$timeToMidnight = $now->setTimezone(new DateTimeZone('Europe/London'))->diff(new DateTime('tomorrow'))->format('%h hours, %i minutes and %s seconds');
The code is working, however it seems to be one hour behind (using GMT -1). At the moment the time is 11:49PM and the output is this:
1 hours, 10 minutes and 36 seconds
I've double checked my php.ini and I also have that timezone set as GMT:
date.timezone = Europe/London
This is also confirmed by checking phpinfo().
What gives? Why isn't my application using the correct timezone?
I tested this on Linux PHP 5.5.5, with Europe/London set as the timezone in php.ini. I actually set the clock back four hours to do this, too. The minimal code I used to reproduce was:
$d = new DateTime('tomorrow');
echo $d->format('c e');
The (correct) output was:
2013-10-27T00:00:00+01:00 Europe/London
I am going to look for a bug in PHP or a bug in the timezone data. To find out which, we'll see what some other program makes of midnight in London tonight. Epoch Converter tells me this should have a Unix timestamp of 1382828400. To double check that timestamp, I ran in PHP:
$d = new DateTime('27-10-2013');
echo $d->format('U');
It also returned 1382828400. So, let's see what it's supposed to show...
TZ=Europe/London date --date="#1382828400" +%c
The output was:
Sun 27 Oct 2013 12:00:00 AM BST
Correct! So tzdata is fine. So let's look at PHP.
I ran your sample code, along with the date command, and got the following output:
1 hours, 29 minutes and 53 seconds
Sat Oct 26 21:30:07 UTC 2013
Sat Oct 26 22:30:07 BST 2013
This is, of course, correct.
I think at this point we have ruled out bugs in both tzdata and PHP, and need to look at configuration issues and programmer expectations.
First, as I noted previously, Europe/London is not UTC, which has no concept of summer time and thus does not change twice per year. Since it doesn't cause such problems, it's a best practice for servers to run on UTC, regardless of what time zone their users are in, and a best practice for programs to use UTC internally and then convert to/from local time zones for display and user input only.
My best guess is that your server's running PHP is actually set to use UTC and not Europe/London as its default time zone. This is the only configuration in which I could reproduce your issue. The results of that test were:
date.timezone = UTC
2 hours, 24 minutes and 36 seconds
Sat Oct 26 21:35:24 UTC 2013
Sat Oct 26 22:35:24 BST 2013
Going forward, you should work in UTC (and with Unix timestamps) wherever practical, and convert to local time as early in processing user input, and as late in displaying it, as you can. An edge case like this one, where summer time is about to end, may be an exception, but you have to be extra careful to ensure that each new DateTime object you construct has the correct time zone set when you construct it, and also be aware that they will have issues like this.
See also the huge and informative Daylight saving time and time zone best practices
Finally, to "fix" your code, let's do this:
$tz = new DateTimeZone('Europe/London');
$now = new DateTime('now', $tz);
$midnight = new DateTime('tomorrow', $tz);
$timeToMidnight = $now->diff($midnight);
echo $timeToMidnight->format('%h hours, %i minutes and %s seconds');

What happened on Dec 31 1969 at 7:00 PM

Every time in PHP when I make a variable such as this one:
$date = strtotime($row['date']);
$date = date("M d Y \a\\t g:i A", $date); // Mmm dd YYYY at h:mm PM/AM
and somehow row['date'] happens to be 0, the date Dec 31 1969 at 7:00 PM is displayed on the screen? Google does not tell me much, I was wondering if this date had any significances.
The Unix epoch is the time 00:00:00 UTC on 1 January 1970. This is the reference point for all time stamps. When you use PHP's date/time functions, you're always working with the number of seconds since the epoch. Time 0 is the epoch, and you (or your web server) must be on the east coast of the US, which is 5 hours behind UTC time.
I find it funny that not a single response here attempted to answer your actual question, which was (if I can paraphrase) "What is the significance of the actual date of Unix epoch time"?
I'm not an expert on the subject but basically, as I understand it, the concept of epoch time was invented in 1971. The programmers chose the arbitrary date of January 1, 1971 GMT to be epoch time. This was partly due to the fact that older computers couldn't handle large numbers so the date had to be in the recent past. Afterwards, epoch time was adjusted to be Jan 1, 1970 so as to be a nice, round number.
So basically, nothing "happened" on that date. It was an arbitrary date chosen based on the original time of the work being done.
Unix timestamps are measured in "time since the Unix Epoch", which is Midnight GMT at the end of Dec. 31 1969 (a.k.a. 00:00 GMT Jan 1 1970). Since you appear to be on Eastern Standard Time, which is GMT-5, you get 7pm Dec. 31st 1969 for a unix timestamp value of 0.
Let me guess: you live on the east coast of the USA?
PHP, like many other systems uses the Unix epoch to measure time, i.e. a value of 0 represents January 1, 1970, midnight UTC - which is the same as Dec 31 1969 at 7:00 PM Eastern Standard Time.
One format in which date objects are stored is the time in seconds that have elapsed from an arbitrary start time. Asking for a formatted version of "0" is like asking for that arbitrary start time. I don't remember why that date was chosen, but I'm sure Wikipedia does. See the article on Unix time below.
Read about Unix Time

Categories