Why strtotime subtracts 2 hours automatically? - php

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.

Related

How can I overwrite timestamp to save into the database base on specific timezone?

Right now my Laravel application save() any items into the database base on this timestamp. America/New_York because I configured it as 'timezone' => 'America/New_York', in config/app.php.
Goal
I wish to overwrite timestamp based on other tz instead, ex. America/Chicago
How do I do that?
You don't need too
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
see https://dev.mysql.com/doc/refman/5.7/en/datetime.html
So when you change the server to another timezone all timestamps will get the new time zone
setting the time zone goe like
SET GLOBAL time_zone = 'America/Chicago';
You don't have to do crazy stuff... What you have to do is:
Store the time in a known timezone and never change that timezone again, it would be awesome if you use UTC as a default timezone.
When you want to "convert" a timezone, you just $model->created_at (or anything that is a Carbon object) and do $model->created_at->setTimezone('America/Chicago'); (for example).
The main idea is that when you already have a Carbon instance with a timestamp, you just change the timezone with setTimezone to the new one you want and it will return a new Carbon instance with that timezone...
Have a look at this SO topic.
Also, remember that timestamp is just an integer representing how many seconds have passed since 1970-01-01 00:00:01 (UTC), so if you say "give me a timestamp of a specific date and time on specific timezone" the timestamp will be always the same even if you change the timezone each time... that is the main idea of the timestamp...
If I say "What timestamp is for 1970-01-01 00:00:10?", if you are on UTC you would get 10, because 10 seconds passed since that specific datetime, if you are on UTC+1, it would still be 10 seconds, but you will display 1970-01-01 00:01:10, because you are 1 hour ahead of UTC, if you are on UTC-1 it will be 1969-12-31 23:00:10, because you are 1 hour behind UTC, but you know how to do the conversion, that is why the value will be always the same disregarding the timezone, and that is also why it is 1970-01-01 00:00:00 and not any other specific datetime, because if you do not know which is the specific datetime you would not know how to do the conversion.
It is very important that you understand what you are working with, so to help you understand better, have a look at this blog explaining the same thing but in more detail.
The timestamp generated in PHP is in UTC time regardless of your local timezone setting.
You can adjust the timezone of the timestamp before it is displayed in the UI using setTimezone.
Reference:
https://www.php.net/manual/en/function.time.php
https://www.php.net/manual/en/datetime.gettimestamp.php

php unixtime, time() and timezones [duplicate]

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.

PHP mktime and timezone

I'm working on some time related features and I opt to always use UTC times and store time stamps as integers for consistency.
However, I noticed that when I use mktime it seems that the currently set time zone has an influence of the return value of mktime. From the documentation I understand that mktime is supposed to return the number of seconds since epoch:
Returns the Unix timestamp corresponding to the arguments given. This
timestamp is a long integer containing the number of seconds between
the Unix Epoch (January 1 1970 00:00:00 GMT) and the time specified.
http://php.net/manual/en/function.mktime.php
However, it seems that mktime is including the time zone that is currently set. When using the following code:
date_default_timezone_set('UTC');
$time = mktime(0, 0, 0, 1, 1, 2016 );
echo "{$time}\n";
date_default_timezone_set('Australia/Sydney');
$time = mktime(0, 0, 0, 1, 1, 2016 );
echo "{$time}\n";
I would expect the two time vales to be same but apparently they are not:
1451606400
1451566800
Which seems to be exacly an 11 hour difference:
1451606400 - 1451566800 = 39600 / (60*60) = 11
What do I not understand correctly about mktime and/or why is the time zone taken into account when using mktime?
I can't tell you why it is the way it is (PHP has never made sense to me when it comes to date and time) but there is an alternative function gmmktime() which is
Identical to mktime() except the passed parameters represents a GMT date. gmmktime() internally uses mktime() so only times valid in derived local time can be used.
There is also a comment on the PHP documentation for this function which explains how mktime(), gmmktime() and time() work. Essentially, they assume that you always think in time zones even if a UNIX timestamp itself doesn't carry a timezone.
Resulting Unix timestamp are indeed encoded in a timezone agnostic way, but input arguments are interpreted relative to the timezone set for current process. And indeed, Sidneys 2016-01-01 00:00:00 (GMT+11) happened 11 hours before UTC 2016-01-01 00:00:00.
When some foreigner tells you a time, you have to know its time zone to correctly interpret it, and so does mktime().
If dates you want to pass to mktime() are UTC dates, then use gmmktime() which exists for that purpose.

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.

Help with UNIX time to human time

I need to format a UNIX timestamp in GMT format to a local date/time. I'm using gmstrftime to do this and I can get the correct result if I use an offset. I just so happen to know what my offset is for the pacific timezone but I don't want to have to get the correct time like this. I've used date_default_timezone_set so gmstrftime is reporting the correct timezone but the time is off by like a day.
I don't get it. If gmstrftime knows what timezone I'm in, why is the time off?
If you have the correct timezone set (such as with date_default_timezone_set) then you only need to use date() for the formatting, no extra coding. UNIX timestamps are in GMT by definition of a UNIX timestamp -- number of seconds since January 1, 1970 00:00:00 GMT.
gmstrftime will always return the time as UTC, seems like you want strftime.

Categories