PHP IntlDateFormatter::parse Output Timezone - php

I have the following PHP code:
$date = 'janvier 1, 2014 à 5:00PM';
$formatter = new IntlDateFormatter('fr_CA', IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'America/Toronto', IntlDateFormatter::GREGORIAN, 'MMMM d, yyyy 'à' h:mma');
$date = $formatter->parse($date);
var_dump($date);
The output is:
int(1388613600)
This appears to be a UNIX timestamp, which is always UTC, Right? So it's automatically being converted from America/Toronto?
Just confirming that I have this correct. I don't have a lot of experience with PHP and time zones, so I appreciate any help.

Correct. The timestamp is a UNIX timestamp. That is - the number of whole seconds since Jan 1, 1970 UTC, not accounting for leap seconds.
You can verify the timestamp using a site like epochconverter.com
1388613600 = 2014-01-01T22:00:00Z
Then you can check the time zone details at timeanddate.com.
In January 2014, Toronto was on EST, which is UTC-05:00.
This calculation clearly verifies that 22:00 UTC is 5:00 PM EST.

As Marc B mentioned, date('r', 1388613600) returned a formatted version of the date including the timezone offset which was set to +0000.
The output is in fact UTC.
Thanks Marc!

Related

Arithmatic signs are not working properly in strtotime

I want to fetch the correct date as per the timezones.
ex. I have a time zone +5:30 from GMT. if GMT is 30 aug 2016 1:00 pm then for gmt+5:30 should give me 30 Aug 2016 6:30 pm however, adding timezones like that actually subtracts it rather adding.
I have this code:
$a=date('Y-m-d H:i:s');
which gives me 2016-08-30 07:36:01 as per GMT which is correct.
$b="+5:30";
$c=(strtotime($a.$b));
echo($c);
it gives me 30 Aug 2016 02:08:25 which is wrong I should get 30 Aug 2016 13:10:32.
What I mean is, if I am adding the timezone value it is getting subtracted and if I do same with -5:30 as timezone I get the correct result. Can somebody please suggest what am I doing wrong or how this should work actually.
Use DateTimeZone and DateTime objects to make it more obvious while working with timezone offsets:
$a = "2016-08-30 07:36:01";
$b = "+5:30";
$gmtTz = new \DateTimeZone("GMT");
$offset = new \DateTimeZone($b);
$dt = new \DateTime($a, $gmtTz);
$dt->setTimezone($offset);
echo $dt->format("Y-m-d H:i:s"); // "016-08-30 13:06:01"
Try this:
Solution 1 :
$minutesToBeAdded = 330;
$currentDate = date('Y-m-d H:i:s');
$currentTime = new DateTime($currentDate);
$currentTime->add(new DateInterval('PT' . $minutesToBeAdded . 'M'));
$newTime = $currentTime->format('Y-m-d H:i');
Solution 2 :
$currentDate = date('Y-m-d H:i:s');
$dateTime = new DateTime($currentDate);
$dateTime->modify('+330 minutes');
Solution 3 :
$currentDate = date('Y-m-d H:i:s');
$newTime = strtotime($currentDate . ' + 330 minute');
echo date('Y-m-d H:i:s', $newTime);
I think the above solution will be helpful for you though I haven't tested it.
When you use functions like date and strtotime, PHP converts the inputs you supply according to your date.timezone configuration in PHP, which may not be UTC. So it's important to check, or explicitly set, the timezone before you do the conversion.
$date = "30 Aug 2016 1:00 pm";
date_default_timezone_set("UTC");
var_dump(date_default_timezone_get()); // gives us "UTC"
var_dump(date("Y-m-d H:i:s", strtotime($date))); // 2016-08-30 13:00:00
var_dump(date("Y-m-d H:i:s", strtotime($date . "+5:30"))); // 2016-08-30 07:30:00
So now you're wondering why you just went back in time 5 hours and 30 minutes. Well, if you look at the actual Unix timestamp from strtotime the truth is revealed about what date and strtotime are doing.
var_dump(strtotime("30 Aug 2016 1:00 pm"), strtotime("30 Aug 2016 1:00 pm +5:30"));
This gives you...
int(1472562000)
int(1472542200)
In the first case, strtotime takes the input string "30 Aug 2016 1:00 pm" and converts it to a Unix timestamp under the assumption that we're currently in UTC. In the second case, it takes the input string "30 Aug 2016 1:00 pm +5:30", which already has a GMT offset of +5:30. So it assumes that we're 1:00 PM in GMT+0530, and it tries to convert that back to UTC (i.e +0000), meaning it now needs to subtract 5 hours and 30 minutes to get to UTC, which gives you "30 Aug 2016 7:30 am"
It's easier to avoid all this confusion when you use DateTime, because you can explicitly specify the timezone or the GMT offset and not be subject to implicit timezone conversion. Also, it's important to note that in PHP a timezone is more than just a GMT offset. PHP uses the Olson Timezone Database to reliably and accurately convert date/time information across different timezones, since GMT offsets can actually vary throughout the year in different timezones.
// DateTime doesn't try to convert this because you told it what the timezone is
$dt = new DateTime("30 Aug 2016 1:00 pm", new DateTimezone("UTC"));
// now lets try with the offset
$dt->setTimezone(new DateTimezone("Asia/Kolkata"));
var_dump($dt->format("j M Y g:i a")); // "30 Aug 2016 6:30 pm"
Notice, there's no need for you to actually mess around with how many hours/minutes to add/subtract. PHP figures it all out by looking up the needed timezone information in the database. Because we correctly specified the timezone supplied and the timezone converted we can rest assured we always have the accurate time regardless of how many times we subsequently convert between timezones. It's a far more reliable abstraction than what you're trying to do.

Is there a referentially transparent way to work with times in php

I am trying to convert times to and from the following timezones, regardless of when or where the code is run:
The timezone of the running code
AEST (Australian Eastern Standard Time)
EDT (New York Eastern Daylight Time)
For example, given a unix timestamp, how do I find a new unix timestamp "monday the same week" using EDT timezone? How do I do this, such that it will always give the same result?
First you have to understand that a Unix Timestamp has nothing to do with timezones, it is always relative to UTC/GMT. To quote from the manual
Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).
Now that you know one timestamp represents a fixed time in reference to GMT/UTC you can go ahead and change time zones in your code to calculate time for them form the same timestamp.
Let us say you have a unix timestamp
$ts = 1171502725;
If you create a date from it you would do something like
$date = new DateTime("#$ts");
echo $date->format('U = Y-m-d H:i:s T') . "\n";
Now you want to see what does that correspond to in EST, you can do
$date->setTimezone(new DateTimeZone('America/New_York'));
echo $date->format('U = Y-m-d H:i:s T') . "\n";
Similarly for CST
$date->setTimezone(new DateTimeZone('America/Chicago'));
echo $date->format('U = Y-m-d H:i:s T') . "\n";
And so on :)
Output
1171502725 = 2007-02-15 01:25:25 GMT+0000
1171502725 = 2007-02-14 20:25:25 EST
1171502725 = 2007-02-14 19:25:25 CST
Fiddle
You can get a list of supported timezones and their identifiers from the PHP Manual

PHP date timestamp timezone not converted properly

So I have this code:
$timestamp = 1414708099;
echo $timestamp;
$date = date_make_date($timestamp, 'UTC', 'datestamp');
date_timezone_set($date, timezone_open('America/New_York'));
$timestamp = $date->format('U');
echo '<br>';
echo $timestamp;
which is supposed to convert the timezone of the initial timestamp from UTC to new york.
but then this ends up printing
1414708099<br>1414708099
hence the timezone didnt change...
what did I do wrong?
btw it also uses Drupal 6 date_api.module: http://drupalcontrib.org/api/drupal/contributions!date!date_api.module/function/date_make_date/6
As per comments
A timestamp is always UTC. You can't apply a time zone to a timestamp - consider its timezone as 0. Whatever you do, it stays 0. You asked for a date formatted with U - manual states this:
U: Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT).
You can't get seconds from Unix Epoch for New York. That number is the same for any location in the world.
Now, had you formatted that date using, say, $date->format('Y-m-d H:i:s') then you would get correctly formatted time with the timezone offset for New York.
Long story short - there is no problem whatsoever here. It all works as intended.

Php strtotime returns wrong timestamp

I do
strtotime("2008-09-04")
Where 09 is the month and 04 is the day and I get the result:
1220500800
Which is Thu, 04 Sep 2008 04:00:00 GMT. Where does those 4 hours come from? I should get 1220486400 instead of 1220500800 from strtotime.
You can set timezone globally with function date_default_timezone_set('UTC');, or you can just set timezone locally when you call strtotime() function like:
echo strtotime("2008-09-04 +0000"); # 1220486400
As people above have said, you're likely suffering from a time zone mismatch. This function may be of use in debugging the issue: http://us3.php.net/date_default_timezone_get
The most common problems with PHP's strtotime are timezones and date-time formats. I will address those 2 points.
First the format. As suggested by others on stackoverflow use the iso 8601 date format YYYY-MM-DD (https://www.iso.org/iso-8601-date-and-time-format.html). For example, September 27, 2012 is represented as 2012-09-27.
Next the timeszones. The best of all , do not use any timezone use the Universal Coordinated Time UTC (which is universal time and corresponds with GMT without Daylight Saving). UTC is the time standard commonly used across the world. The world's timing centers have agreed to keep their time scales closely synchronized - or coordinated - therefore the name Coordinated Universal Time (https://www.timeanddate.com/time/aboututc.html).
So now we have the picture clear. To convert a date time into unixtimestamp do:
// Saves your local set Timezone.
$saveDDTZ = date_default_timezone_get();
// Sets the timezone to UTC
date_default_timezone_set("UTC");
// Converts a date-time into a unix timestamp (= 1560470400).
$unixTS = strtotime( "2019-06-14 00:00:00 UTC");
// Restore the timezone
date_default_timezone_set($saveDDTZ");
To restore a unix timestamp to a Date use:
// Saves your local set Timezone.
$saveDDTZ = date_default_timezone_get();
// Sets the timezone to UTC
date_default_timezone_set("UTC");|
$unixTS = 1560470400
$dateTime = date("Y-m-d H:i:s", $unixTS);
// Restore the timezone
date_default_timezone_set($saveDDTZ");
If you want to change the UTC date into a TimeZone use the difference of the UTC and the TimeZone and the Daylight Saving.

Using strtotime and taking timezone into consideration

I have a system running in PHP and am using CodeIgniter (if there is a CI specific answer to this I would be happy as well).
I often need to figure out the timestamp of dates such as "this Thursday" or "this Monday". I currently use strtotime("this Thursday") and it gives me what I ask for.
I have a server in EST. It is 01:00 (1:00am), early morning Friday, Feb 24, 2012 in New York.
I have a user who has specified his timezone to be Pacific time. Right now it is 22:00 (10pm) late evening Thursday Feb 23, 2012 in San Francisco.
I use strtotime("this Thursday"). Since my server is in EST, it returns me the timestamp for March 1, 2012. I would like to take the user's timezone into consideration. For my user, "this Thursday" should return Feb 23, 2012.
Can I use strtotime("this Thursday") for it, and if so, how would I specify the target timezone?
If not, what approach would you suggest to getting the date for "this Thursday" in a specific timezone.
The manual for strtotime links directly to date_default_timezone_set. I would take that as a hint to use that.
I just figured out that strtotime takes a $now parameter. I can specify the $now param to be the current time in the user's timezone and strtotime returns me what I need.
This is taken string from the php site
<?php
date_default_timezone_set('Asia/Shanghai');
$first_day_of_month = date('Y-m',time()) . '-01 00:00:01';
$t = strtotime($first_day_of_month);
print_r(array(
date('Y-m',$t),
date('Y-m',strtotime('- 1 month',$t)),
date('Y-m',strtotime('- 2 month',$t)),
));
?>

Categories